An open-source birthday landing page built to offer smooth animations, interactive features, and straightforward environment-driven customization. Created by Naboraj Sarkar.
📺 Click the thumbnail above to watch the official Birthday Bloom project overview.
Want to contribute to an active open-source project? We love contributions from first-time developers!
# 1. Clone your fork
git clone https://github.com/naborajs/birthday-bloom.git
cd birthday-bloom
# 2. Install dependencies
npm install
# 3. Start local development server (with HMR)
npm run dev
# 4. Run tests and full CI verification
npm run verify👉 Check out our Good First Issues and the Root Contributing Guide to get started!
Birthday Bloom is now env-first & zero-config: names, relationship type, messages, colors, photos, captions, videos, audio, visible sections, animation behavior, accessibility, and family-template metadata can be changed from .env.local or instant URL query parameters.
Repository: naborajs/birthday-bloom
Important: when this project says "env", it means environment variables, usually stored in .env.local during local development or in the hosting provider's Environment Variables/Secrets panel during deployment. These values are the intended customization layer. For normal changes, do not rewrite the app code.
If you ask an AI coding agent to customize Birthday Bloom, tell it this first:
This project is already built to be customized through env values and URL parameters. Before editing components or templates, check
.env.example,obsidian-docs/URL-Parameters.md, andobsidian-docs/ENV_GUIDE.md, then tell me which env keys or parameters to update.
Direct docs:
- Zero-Config URL Parameters Guide
- Complete env customization guide
- Multi-Language Localization (French) guide
- Multi-Language Localization (Bengali) guide
- Multi-Language Localization (Hindi) guide
- Quick start
- Family system
- Template architecture
- Developer guide & Contributor Walkthroughs
- Migration guide
- Documentation index
Copy .env.example to .env.local, change values, restart the dev server, and the experience updates without component edits.
This project provides a deeply emotional, personalized birthday celebration landing page built with React 18, TypeScript, Framer Motion, Three.js / React Three Fiber, Tailwind CSS, and Zustand.
- Instant URL Query Customization & Zero-Code Sharing: Create and share personalized surprises instantly via URL parameters (e.g.
?name=Sophia&rel=partner&lang=en&sender=Alex) without modifying code. - 1-Click Viral Social Sharing & Referral Modal: Built-in glassmorphic sharing suite for WhatsApp, X (Twitter), Telegram, Facebook, LinkedIn, and native Web Share API with UTM tracking.
- Advanced Dynamic SEO & Generative Engine Optimization (GEO): Reactive document head manager (
useDynamicSEO.ts), full Schema.org structured data (WebSite,WebApplication,FAQPage,HowTo,BreadcrumbList,SocialEvent), multilingual sitemap withhreflangalternates, and AI bot discovery rules. - 4 Authentic Multi-Language Localization Engines: Culturally tailored emotional letters, wishes, quotes, and UI copy in English (
en), Bengali (bn), Hindi (hi), and French (fr) with grapheme-safe typography. - 3D WebGL Cake Cutting & Candle Blowout: Real-time Three.js procedural cake with interactive slice separation physics (
@react-spring/three), candle blowout detection, and reduced-motion support (VITE_REDUCED_MOTION). - Interactive Birthday Quiz: A gamified trivia section that adapts questions dynamically based on the recipient's hobbies, interests, and relationship.
- Polaroid Memory Gallery: A responsive 3D-tilt photo carousel with caption reveals, lightbox support, and an automatic multi-language placeholder card when custom photos are omitted.
- Interactive Canvas Fireworks & Ambient Effects: 60fps HTML5 Canvas 2D fireworks (
PremiumFireworks), sparkle rain (SparkleRain), organic fireflies (FireflyEffect), and interactive emoji cursor trails (EmojiCursorTrail). - Procedural HeartTree Finale: An emotional climax drawing an SVG blooming tree with dynamic stage growth and personalized quotes.
- 53 Environment Variables & Aliases: 100% customizable without touching source code or JSX via
.env.localor hosting dashboards.
📖 Watch the Complete Birthday Bloom Explainer (8 Minutes)
Learn everything about Birthday Bloom—from the problem it solves, its vision, core features, customization options, workflow, open-source philosophy, future roadmap, and how you can use and contribute to the project.
Most landing page templates are static. Birthday Bloom treats the browser as a stage, using a linear state machine (splash unlock intro main) to control narrative pacing, interactive transitions, and audio/haptic sensory feedback.
By coordinating asynchronous delays and Framer Motion timelines, the application guides the user through typing scenes, simulated chats, and final interactive reveals.
- Optimized 60fps Performance: Procedural 3D elements (Three.js / R3F) are code-split into lazy chunks (
dist/three.*.js), while ambient layers use lightweight Canvas 2D and hardware-accelerated CSS keyframes to ensure silky 60fps performance on mobile and desktop devices. - Engaging Text Flow: Grapheme-safe typewriter animations, cursor tracking, and simulated messaging windows build an authentic, heartfelt narrative pace.
- Environment-Driven Configuration: Customize the name, relationship, language, messages, colors, and media by simply setting variables in a single
.env.localfile without editing code. - Vite Build System: Instant Hot-Module-Replacement (HMR) during local development and optimized assets for production deployments.
If you want to deploy Birthday Bloom on the web to share with your loved one, you can do it completely free on Vercel. You don't need any coding experience to follow these steps!
If you prefer a visual guide, click the thumbnail below to watch the complete step-by-step walkthrough:
🚀 Watch the Complete Deployment Guide
Learn how to deploy Birthday Bloom step by step using Vercel. This guide covers everything from forking the GitHub repository, importing the project into Vercel, configuring environment variables, deploying your website, customizing it, and publishing updates. Perfect for beginners and experienced developers alike.
Goal: Get a free space to hold your copy of the website code.
- Direct Link: 👉 GitHub Sign Up
- What to do: Enter your email, create a password, choose a username, and complete the sign-up.
- Why: You need a GitHub account so that Vercel can pull the code and build it for you.
Goal: Copy all of Birthday Bloom's files to your new GitHub account.
- Direct Link: 👉 Fork Birthday Bloom
- What to do:
- Leave the Repository name as
birthday-bloom.- Make sure the checkbox "Copy the main branch only" is checked.
- Click the green
Create forkbutton at the bottom of the page.- Why: This creates a copy under your name (e.g.,
github.com/your-username/birthday-bloom), allowing you to link it to Vercel.
Goal: Sign up for the hosting service that will put your website online for free.
- Direct Link: 👉 Vercel Sign Up
- What to do: Click the
Continue with GitHubbutton. This automatically links your Vercel account to your GitHub account.- Why: Linking with GitHub allows Vercel to read your code copy and automatically deploy updates.
Goal: Tell Vercel to start setting up your birthday website.
- Direct Link: 👉 Vercel - New Project Dashboard
- What to do:
- Under the "Import Git Repository" section, locate the repository named
birthday-bloom.- Click the black
Importbutton next to it.- Why: This imports the project files into Vercel so it can start setting up your deployment.
Goal: Set the name, date, messages, and colors for the birthday person without touching any code.
- What to do:
- On the project setup page in Vercel, find the section labeled
Environment Variables(it is a dropdown panel). Click it to expand.- For each variable below, type the Key in the first field, the Value in the second field, and click the blue
Addbutton:
Key (Environment Variable) Example Value What it controls VITE_BIRTHDAY_NAMESarahThe name of the birthday person (skips setup wizard automatically). VITE_BIRTHDAY_DATE2026-07-25The birthday date in YYYY-MM-DDformat (sets up countdown & passcode).VITE_BIRTHDAY_RELATIONSHIPfriendRelationship type ( partner,friend,sister,brother,mother, etc.).VITE_BIRTHDAY_CUSTOM_MESSAGEHave the most wonderful birthday!Heartfelt custom message shown before the cake reveal. VITE_BIRTHDAY_COLOR#FF6B6BGlobal theme color accent (e.g. coral: #FF6B6B, cyan:#00C2FF, gold:#FFD700).[!TIP] For a full list of all 30+ customizable items (photos, music, videos, animations, and family templates), check the .env.example configuration file or the Environment Variables Guide section below.
Goal: Build the site and make it live.
- What to do: Click the blue
Deploybutton at the bottom.- What happens next: Vercel will spend about 60–90 seconds building your site. Once done, it will show a preview screen of your website with a shower of confetti!
- Why: This turns your source code files into a live, interactive website accessible from any phone or computer.
Goal: Send the surprise to your loved one!
- What to do:
- Click on the screenshot preview of your website in Vercel to open it.
- Copy the URL from your web browser's address bar. It will look like:
https://birthday-bloom-yourname.vercel.app- Send this link to the birthday person!
- Key Features & Interactive Elements
- 📸 Visual Showcase & System Architecture
- Animation & Pacing Principles
- Mastering the Lifecycle
- In-Depth Code Explanation
- Personalization & Customization
- Environment Variables & Configuration Guide
- Advanced Installation & Setup
- Troubleshooting & Massive FAQ
- File-by-File Responsibility Map
- Localized Setup
- Mastering SVG Animations
- Containerization & Deployment
- Contributing Guidelines
- Author & Socials
- License
Birthday Bloom orchestrates an end-to-end emotional narrative through a five-phase state machine:
- Splash Gate: Initial tap-to-begin gesture priming audio playback and haptic feedback.
- Security Gate: Secret birthday passcode verification with dynamic hint generation.
- Cinematic Intro: Storytelling kinetic typography, simulated chat messages, and wax-sealed parchment letter reveal.
- Interactive Main Stage: 3D Three.js WebGL cake cutting, candle blow interaction, balloon pop game, polaroid memories, trivia quiz, Tinder-style wishes deck, and mystery gift box.
- Viral Sharing Hub: Instant URL generation with query parameters and native multi-platform social sharing modal.
| 1. Splash Screen Gate | 2. Secret Passcode Unlock |
|---|---|
| Atmospheric welcome glass card priming audio playback. | Passcode entry with dynamic hint based on birthdate format. |
| 3. Cinematic Storyteller | 4. Grand Celebration Hero Stage |
|---|---|
| Heartfelt kinetic text with pulsing aura and particle rain. | Multi-color typography, 3D rotating cake, and dynamic confetti. |
| 3D Cake Flavor Selector | Real-Time 3D Candle Blow & Slice |
|---|---|
| 4 luxury cake flavors with procedural shaders & pedestals. | Interactive candle blowout detection with slice physics. |
| Balloon Pop Mini-Game | Wax-Sealed Parchment Love Letter |
|---|---|
| Floating balloons with pop physics and hidden message. | Interactive wax seal with unfolding vintage parchment letter. |
| Interactive Birthday Trivia Quiz | Tinder-Style Wishes Deck |
|---|---|
| Gamified multiple-choice quiz tailored to recipient hobbies. | Swipeable card deck with love reactions and sweet wishes. |
| Mystery Gift Box & Party Tease | Surprise Unlocked Modal Dialog |
|---|---|
| Glassmorphic teaser card with custom gift code. | Party hype tease followed by celebratory code reveal. |
| Interactive Celebration Action Buttons | Video Memories Gallery |
|---|---|
| Interactive Cannon, Party, Love, and Share triggers. | Curated video clip gallery and cinematic memory reel. |
| 1-Click Viral Sharing Modal | Custom 404 Experience |
|---|---|
| Instant social sharing for WhatsApp, X, Telegram, and link copy. | Glassmorphic fallback screen with quick-navigation buttons. |
Birthday Bloom provides culturally authentic celebrations in four languages, adjusting idioms, relationship themes, and typography:
| Bengali Preset (বাংলা) | Hindi Preset (हिंदी) | French Preset (Français) |
|---|---|---|
| শুভ জন্মদিন (Shuvo Jonmodin) | जन्मदिन की हार्दिक शुभकामनाएँ | Joyeux Anniversaire & Romance |
| Mobile Celebration Hero | Mobile 3D Cake Cutting |
|---|---|
| Touch-first responsive layout with dynamic confetti. | Smooth WebGL rendering optimized for mobile GPUs. |
Birthday Bloom operates as a structured timeline. The following diagram shows the chronological flow of scenes and interactive features from boot to the viral sharing stage:
graph TD
Splash[Splash Screen] -->|Tap to Begin| Gate{Password Required?}
Gate -->|Yes| Unlock[Password Unlock Gate]
Gate -->|No| Intro[Cinematic Intro]
Unlock -->|Passcode Verified| Intro
Intro -->|Kinetic Text| Story[Storyline Narrative]
Story -->|Simulated Chat| Chat[Fake Chat Scene]
Chat -->|Wax Seal Letter| Letter[Envelope Love Letter]
Letter -->|Complete| Main[Main Celebration Experience]
Main -->|WebGL Three.js| Cake[3D Cake Cutting & Candle Blow]
Main -->|Mini-Game| Balloons[Balloon Pop Mini-Game]
Main -->|Polaroid Tilt| Gallery[Memory Photo Gallery]
Main -->|Trivia| Quiz[Birthday Trivia Quiz]
Main -->|Swipe Cards| Deck[Wishes Deck]
Main -->|Tease & Reveal| Gift[Mystery Gift Box]
Main -->|Cinema Reel| Videos[Video Memories]
Main -->|SVG Climax| HeartTree[Heart Tree Finale]
Main -->|1-Click Share| Share[Viral Sharing Hub]
Figure: Scene progression flow and interactive features from boot to the grand finale.
The project resolves environment variables and hydrates application state through a central config layer:
flowchart LR
Env[Environment Config / URL Query] -->|"Load at runtime"| Config[Config Parser]
Config -->|"Hydrate state"| Store[Zustand State Store]
Store -->|"Inject values as props"| Components[React Components]
Figure: The data flow from raw environment variables and URL parameters to component properties.
The sequence is divided into two distinct interaction stages: the boot-to-intro phase, and the main dashboard user actions.
Part A: Boot & Intro Sequence
sequenceDiagram
actor User
participant App as "App.tsx"
participant Intro as "CinematicIntro.tsx"
participant Store as "useBirthdayStore.ts"
User->>App: Open Site
App->>Store: Initialize Configuration
App->>Intro: Mount Intro Component
loop Typing Sequences
Intro->>Intro: Play storytelling lines
Intro->>Intro: Play fake-chat typing
Intro->>Intro: Play birthday reveal
end
Intro->>App: Trigger onComplete Callback
App->>Intro: Unmount Intro Component
Figure: Interaction sequence during the initialization and cinematic intro stages.
Part B: Main Dashboard Interactions
sequenceDiagram
actor User
participant Dashboard as "MainBirthday.tsx"
participant Cake as "CakeCutting.tsx"
participant Confetti as "useConfetti.ts"
User->>Dashboard: View Dashboard
Dashboard->>Cake: Render SVG Cake UI
User->>Cake: Click "Blow Candles"
Cake->>Cake: Extinguish SVG flames
Cake->>Confetti: Fire Corner Cannons
User->>Cake: Cut Cake
Cake->>Cake: Split SVG cake layers
Figure: User interactions within the main dashboard and interactive cake cutting engine.
The animation sequence relies on a state machine configured in the entry files. Understanding how these scenes transition is essential before modifying the code.
flowchart LR
Boot[Boot Initializer] -->|Mount| Intro[Cinematic Intro]
subgraph State Machine Phases
Intro --> Story[storytelling scene]
Story -->|"Lines Complete"| Chat[fake-chat scene]
Chat -->|"Typing Complete"| PostChat[post-chat scene]
PostChat -->|"Reveal Trigger"| Reveal[reveal-sequence scene]
Reveal -->|Transition| Done[done scene]
end
Done -->|"Complete Callback"| Main[Main Birthday View]
Figure: The finite state machine phases and transitions of the application.
- Boot:
App.tsxinitializes, loads configuration settings, and decides whether to play the intro sequence based on setup parameters. - Mount:
CinematicIntro.tsxmounts and maps over the custom narrative lines. Timers trigger transitions sequentially. - Execution: During the chat phase, sequence timers control text entry, deletions, and sending animations to simulate active conversations.
- Transition: When the intro completes, the
onCompletecallback triggers the entry component to unmount the intro stage and render theMainBirthday.tsxdashboard. Modifying or removing these timers without care can lock the user inside the intro phase.
Because Birthday Bloom is designed to be fully customizable, the following sections deeply analyze exactly how the components function beneath the hood. If you intend to change pacing, layout, or animations, refer to this manual.
The CinematicIntro component is the bridge between the Splash Screen and the Main Dashboard. It handles a multi-phase emotional sequence.
Code Breakdown:
- State Machine: It uses a strongly typed literal state:
type Scene = "storytelling" | "fake-chat" | "post-chat" | "reveal-sequence" | "done". - Timer Management: Instead of having floating timeouts that could cause memory leaks if a user unmounts early, we use
useRef<ReturnType<typeof setTimeout>[]>([]);to store all timeout IDs, clearing them aggressively when the component unmounts or transitions. - The TypeWriter Component: We use a custom
TypeWritercomponent to begin rendering the string character-by-character based on specific speed delays. - Visuals: Uses dynamic localized backgrounds. Depending on the
scenestate, the background shifts from dark blues to deep maroons, building tension.
The most complex interactive piece of the platform.
Code Breakdown:
- SVG Mastery: The cake is drawn entirely with SVG. This prevents pixelation on high-density Retina displays (iPad Pro, 4K monitors, etc.).
- Layers & Slices: The SVG groups (
<g>) are structurally separated into left and right halves. - The Knife Phase:
- Phase 1: User selects a themed cake (Chocolate, Strawberry, Velvet).
- Phase 2: User triggers the "Blow Candles" mechanic. This toggles a boolean (
candlesLit), transforming the animated SVG<ellipse>flames into rising smoke paths linearly. - Phase 3: The
KnifeSVGenters with a CSS transform, splitting the left and right halves by applyingtranslateXandrotatestyles to the SVG groups.
- Custom Easing: The cake splits using
cubic-bezier(0.34, 1.56, 0.64, 1), a "bounce" easing that gives it physical weight, instead oflinearorease-in-out.
When building emotional tension, reading speed is everything. We moved away from instant text rendering to a programmatic typing approach.
Code Breakdown:
useEffect(() => {
if (!started) return;
if (displayed.length < text.length) {
const timer = setTimeout(() => {
setDisplayed(text.slice(0, displayed.length + 1));
}, speed);
return () => clearTimeout(timer);
} else {
setDone(true);
onComplete?.();
}
}, [started, displayed, text, speed, onComplete]);- Recursive Growth: It takes the current string, measures it against the target string length, and pushes exactly one additional character into the buffer.
- Cursor Blinking: A span element styled with
animate-blinkexists at the end of the text node while typing. Oncedoneis true, the cursor hides gracefully, handing focus to the next element.
A new, premium addition to the end of the user experience. The growing Heart Tree serves as an emotional crescendo at the very bottom of the website.
Code Breakdown:
- Sequential SVG Drawing: Standard SVGs paint instantly. We want the tree to "grow" organically out of the ground. We use
stroke-dasharrayandstroke-dashoffset.- By setting
stroke-dasharrayequal to the total path length, we can completely hide the stroke by settingstroke-dashoffsetto that same length. - A CSS transition reduces
stroke-dashoffsetto0over 1.5 seconds, creating a beautiful drawing effect.
- By setting
- Staging:
Stage 0: Seed/Base.Stage 1: Main thick branches grow.Stage 2: Secondary, thinner branches sprout from the main lines.Stage 3: Heart SVG paths (leaves) translate and scale up securely at branch nodes.Stage 4: A radial CSS gradient overlay fades in, giving the entire tree a mystical "bloom" effect alongside floatingTreeSparksparticles.
The primary dashboard that users explore after the intro completes.
Code Breakdown:
- Hero Stagger: Features a large, centered hero section that fades up on mount. Uses the
TypeWriterto write out the personalizedBIRTHDAY_NAME. - Particle System Integration: Implements both
Confetti.tsxandBalloons.tsx. - Message Card Styling: A meticulously crafted
divutilizingbackdrop-blur-lg(glassmorphism) and a complex dual-layer box-shadow (boxShadow: "0 0 60px hsl(330, 85%, 60%, 0.15)") to create a glowing neon effect against a dark background. - Responsive Typographic Guard: Heavy emphasis on
break-wordsandoverflow-hidden. As the TypeWriter injects strings into the DOM, it forces browser reflows; strict bounds ensure the layout does not jitter or expand horizontally on mobile screens. We lockmin-heightglobally for paragraphs holding TypeWriter instances.
Birthday Bloom is built to be customized using pure Environment Variables (Configuration Engine) and directly modifying assets. You do not need deep React knowledge to make this your own.
- Navigate to
/public/assets/birthday/. - Replace the background images (
birthday-cute.png,birthday-gold.png, etc.) with your own. Ensure they are optimized (WebP format recommended) and less than 500kb each to eliminate load stutter. High resolution images will delay the splash screen logic! - Replace
/public/assets/photo-1.jpg,photo-2.jpg, andphoto-3.jpgwith actual photos of the person. Maintain aspect ratios if possible, or useobject-covertailwind classes if you inject custom resolutions.
If the intro is too slow or too fast:
- Open
src/components/birthday/CinematicIntro.tsx. - Find the timer multipliers (e.g.,
i * 5000mapping over thestoryLines). - Reduce
5000to3500to speed up the pacing between storytelling lines. - Modify the
TypeWriterspeed props tospeed={30}for extremely fast typing, orspeed={120}for dramatic, slow typing.
The entire initialization process is controlled securely via the .env paradigm. If you configure these variables, the website will bypass the setup wizard and immediately start the cinematic experience for the birthday person.
| Variable Name | Required | Default Value | Description |
|---|---|---|---|
VITE_BIRTHDAY_NAME |
YES | "" |
The primary name of the person you are celebrating. Setting this automatically skips the config wizard. |
VITE_BIRTHDAY_AGE |
NO | null |
The age they are turning. |
VITE_BIRTHDAY_GENDER |
NO | "other" |
"male", "female", or "other". |
VITE_BIRTHDAY_DATE |
NO | null |
The specific date of the birthday. |
VITE_LANGUAGE / VITE_LANG |
NO | "en" |
Multi-language localization switch: "en" (English - default), "fr" (French), "hi" (Hindi), "bn" (Bengali). Normalizes aliases (fr/french, hi/hindi, bn/bengali). |
VITE_BIRTHDAY_RELATIONSHIP |
NO | "partner" |
Relationship template: "partner", "friend", "brother", "sister", "father", "mother", "grandfather", "grandmother", "uncle", "aunt", "cousin", "son", "daughter", "guardian", "colleague", "mentor", "family". Fundamentally tailors mood, storytelling text, emotional letters, and emoji effects! |
VITE_BIRTHDAY_WISHER_NAME |
NO | "" |
The birthday wish sender's name, shown in the emotional letter and in the footer. |
VITE_BIRTHDAY_COLOR / VITE_FAVORITE_COLOR |
NO | "#FF6B6B" |
A hex code defining the dynamic global theme, neon glows, and gradient backgrounds. |
VITE_BIRTHDAY_INTERESTS / VITE_FAVORITE_ITEMS |
NO | "" |
Comma-separated list of interests/items to customize ambient particles. |
VITE_BIRTHDAY_LETTER_TITLE |
NO | "" |
Optional heading for the emotional letter card. |
VITE_BIRTHDAY_LETTER_OVERRIDE |
NO | "" |
Replace the generated letter body with your own multi-line letter. |
VITE_BIRTHDAY_CUSTOM_MESSAGE / VITE_CUSTOM_MESSAGE |
NO | "" |
A heartfelt, custom message to reveal with kinetic typography right before the grand cake reveal. |
VITE_PHOTOS / VITE_PHOTO_1..6 |
NO | "" |
Image URLs for polaroid gallery slides. If omitted, an elegant placeholder message is automatically shown. |
VITE_SPECIAL_MEMORIES |
NO | "" |
Special memories in `Title;imageUrl |
VITE_FINAL_VIDEO_URL |
NO | "" |
Final surprise YouTube video URL. Cleanly hidden if omitted. |
VITE_SOUND_URL / VITE_BGM_URL |
NO | "" |
The background music audio URL. |
VITE_SOUND_EFFECTS |
NO | true |
Enable or disable SFX audio feedback. |
VITE_VIDEO_1, VITE_VIDEO_2, VITE_VIDEO_3 |
NO | "" |
Adds video links (YouTube or MP4) to the final cinematic Video Gallery at the bottom of the page. |
VITE_PASSWORD_REQUIRED |
NO | false |
Force enables the password lock page. |
VITE_PASSWORD |
NO | "" |
Manual password override (e.g. love or 1234). |
VITE_PASSWORD_HINT |
NO | "" |
Customized emotional hint displayed if the user gets stuck. |
VITE_PASSWORD_FORMAT |
NO | "MMDD" |
Format to auto-generate password from VITE_BIRTHDAY_DATE if VITE_PASSWORD is not set (e.g., MMDD, DDMM). |
How to set this up locally:
In the root of your project, create a file named .env. Add the following:
VITE_BIRTHDAY_NAME="Riya"
VITE_BIRTHDAY_AGE="25"
VITE_BIRTHDAY_GENDER="female"
VITE_BIRTHDAY_DATE="2026-10-15"
VITE_BIRTHDAY_RELATIONSHIP="partner"
VITE_BIRTHDAY_WISHER_NAME="Alex"
VITE_FAVORITE_COLOR="#00C2FF"
VITE_FAVORITE_ITEMS="coffee, stars, music"
VITE_CUSTOM_MESSAGE="You mean the universe to me."
VITE_VIDEO_1="https://www.youtube.com/watch?v=dQw4w9WgXcQ"To deploy this project to the world for free:
- Push this code to a private or public GitHub repository.
- Log into Vercel and click Add New -> Project.
- Import your GitHub repository.
- Open the Environment Variables section in the deployment settings.
- Add the keys exactly as shown above (
VITE_BIRTHDAY_NAME,VITE_BIRTHDAY_RELATIONSHIP, etc.) and provide the values. - Click Deploy! When the birthday person opens the Vercel link, it will launch their highly customized, surprise experience seamlessly without asking them for setup details.
For developers wanting to run this locally, clone, and fork:
- Node.js
v18.0.0or higher - npm
v9.0.0or higher - Git
- Clone the repository:
git clone https://github.com/naborajs/birthday-bloom.git cd birthday-bloom - Install local dependencies:
npm install
- Environment Setup:
cp .env.example .env # Edit .env with your favorite text editor - Boot the Dev Server:
The server will boot on
npm run dev
http://localhost:5173. Any changes to thesrcfolder will trigger an instant Hot-Module-Replacement (HMR) reload in the browser without losing application state.
Q: The website shows a blank screen on load?
A: Check your browser console. It's likely a missing .env variable or a typo in VITE_BIRTHDAY_NAME. Ensure you have run npm install.
Q: The animation stopped in the middle!
A: This happens if a timer is cleared incorrectly. Ensure you haven't modified the timersRef logic in CinematicIntro.tsx. Check for VITE_BIRTHDAY_DATE formatting errors.
Q: Audio isn't playing on my iPhone? A: iOS requires a "user gesture" to play sound. Ensure you clicked the "Start" button on the Splash Screen.
Q: How do I change the font?
A: Import your Google Font in index.css and update the --font-display variable.
Q: The text is too long and overlaps!
A: Use the VITE_BIRTHDAY_CUSTOM_MESSAGE for long messages. The VITE_BIRTHDAY_NAME should be kept under 15 characters for best results.
Q: Can I add more than 3 photos?
A: Yes, but you must update the photos array in PhotoGallery.tsx and add corresponding VITE_PHOTO_X variables to the store.
Q: How do I deploy to GitHub Pages?
A: Use the gh-pages package or a GitHub Action. Note that client-side routing may require a 404.html redirect hack.
Q: Vercel build failed?
A: Ensure your Node version is 18+. Check for case-sensitive file imports (e.g., Component.tsx vs component.tsx).
Q: How do I remove the "Naboraj Sarkar" branding?
A: You are free to modify the footer in MainBirthday.tsx, but keeping a small "Powered by Birthday Bloom" is appreciated!
The diagram below shows the high-level responsibilities of the primary directories:
graph TD
Root[src directory] --> Components[birthday components]
Root --> Features[features directory]
Root --> Pages[pages directory]
Root --> Config[config directory]
Components -->|Renders| Actors[Interactive Actors]
Features -->|Manages| Back[State and Theme Engine]
Pages -->|Controls| Entry[Index Entry and NotFound]
Config -->|Resolves| ENV[Personalization Fallbacks]
Figure: High-level directory structure and core responsibilities.
Balloons.tsx: Floating SVG background balloons with random drift velocity.CakeCutting.tsx: Interactive birthday cake (handles candle extinguishing, layered SVG splitting, and quotes).CinematicIntro.tsx: Sequence orchestrator running the introduction scene state machine.FakeChatScene.tsx: Simulates the typing and bubbles of the fake messaging interface.FloatingElements.tsx: Manages the floating background particles and dust effects.HeartProgression.tsx: Visual heart tracker showing interaction progress.HeartTree.tsx: Sprouts and draws the growing branches and heart leaves using SVG stroke offsets.MainBirthday.tsx: Main landing view hosting the birthday message and interactive components.PhotoGallery.tsx: Polaroid photo gallery with dynamic 3D tilt effects.Sparkles.tsx: Controls individual sparkle particle emission.TypeWriter.tsx: Typographic component that types strings character-by-character recursively.
cinematic-story: Animation variants and layout details for the intro text sequences.core: Global store (useBirthdayStore), theme loaders (useDynamicTheme), and global utilities.
Index.tsx: Directs routing by rendering either the Splash screen, Cinematic Intro, or Main Dashboard.NotFound.tsx: Custom 404 page for route handling.
Birthday Bloom natively supports English (default), French (Français), Hindi (हिन्दी), and Bengali (বাংলা) with cultural nuance, emotional warmth, and authentic localized templates.
- 🇬🇧 English Quick Start Guide — 5-minute setup with zero code changes.
- 🇫🇷 Guide de Configuration en Français (French Setup Guide) — French emotional letters, quotes, cake names, and tone nuances.
- 🇮🇳 हिंदी सेटअप गाइड (Hindi Setup Guide) — Devanagari typography, Hindi emotional letters, and tone nuances.
- 🇧🇩 বাংলা সেটআপ গাইড (Bengali Setup Guide) — Eastern Nagari typography, Bengali emotional letters, and tone nuances.
To switch languages, set VITE_LANGUAGE=fr (French), VITE_LANGUAGE=hi (Hindi), or VITE_LANGUAGE=bn (Bengali) in your .env.local or hosting provider environment settings.
If you encounter any specific issues with sound, animations, or deployment, please refer to our master troubleshooting suite:
Vercel is the native home for Vite projects.
- Push to GitHub.
- Link repo.
- Environment Variables: Add all
VITE_keys. - Build Settings:
npm run build,distdirectory.
Similar to Vercel, but ensure you add a _redirects file if you use React Router.
For those who want to host it on their own VPS.
FROM node:18-alpine AS build
WORKDIR /app
COPY . .
RUN npm install && npm run build
FROM nginx:stable-alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]SVG is the heart of Birthday Bloom. Unlike raster images (JPEG/PNG), SVGs are code-based, which allows us to animate them with mathematical precision.
We use this for the Heart Tree. By setting stroke-dasharray and stroke-dashoffset to the total length of the path, we can "draw" the tree in real-time.
@keyframes draw {
to { stroke-dashoffset: 0; }
}The 3D Cake isn't just flat shapes. We use <feDropShadow> and <feGaussianBlur> filters inside the SVG <defs> to create dynamic lighting. When you "blow" the candles, the light source shifts, changing the shadows on the cake layers.
While not used extensively yet, our engine supports path morphing. You can transform a circle into a heart by animating the d attribute using Framer Motion.
| Feature | Birthday Bloom | Generic Templates |
|---|---|---|
| Performance | 60fps (GPU Accelerated) | Laggy (CPU intensive) |
| Customization | Zero-Config (.env) | Manual Code Edits |
| 3D Effects | Interactive & Tilting | Static Images |
| Narrative | Finite State Machine | Single Scroll Page |
| Branding | Naboraj Sarkar Premium | Generic / Watermarked |
For large-scale deployments or enterprise-level birthday surprises (yes, they exist), we support full containerization.
Our Docker image is optimized using a multi-stage build to keep the footprint under 50MB.
# Stage 1: Build
FROM node:20-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Serve
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]If you are deploying this for a celebrity or a high-traffic event, use this manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: birthday-bloom
spec:
replicas: 3
selector:
matchLabels:
app: birthday-bloom
template:
metadata:
labels:
app: birthday-bloom
spec:
containers:
- name: birthday-bloom
image: naborajs/birthday-bloom:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: birthday-bloom-service
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: birthday-bloomWe welcome contributions of all types. If you find a bug, want to suggest features, improve documentation, or refine styles, please feel free to open an issue or submit a pull request. We thank everyone who uses, stars, or contributes to this repository.
Birthday Bloom welcomes contributions of all kinds — bug fixes, documentation improvements, UI polish, accessibility enhancements, performance optimizations, and new features.
We have created two animated walkthrough guides to help you contribute to Birthday Bloom:
🤝 Watch the Official Contributing Guide
Learn how to contribute to Birthday Bloom, whether you're a first-time open-source contributor or an experienced developer. This guide covers GitHub Issues, feature requests, bug reports, forking the repository, creating branches, making meaningful commits, submitting Pull Requests, the code review process, and open-source best practices to help you become a successful contributor.
📚 Watch the Complete Contributor Guide
Learn how to contribute to Birthday Bloom from start to finish. This step-by-step guide covers GitHub Issues, feature requests, bug reporting, forking the repository, cloning the project, creating branches, writing meaningful commit messages, opening Pull Requests, the review process, and open-source best practices. Whether you're making your first contribution or you're an experienced developer, this guide will help you confidently contribute to the project.
New! The entire documentation has been rebuilt as an interconnected Obsidian Vault. To access the full depth of system architecture, UI components, and animations:
- Open the Obsidian App.
- Select "Open folder as vault" and choose the
obsidian-docs/folder in this repository. - Start exploring from
obsidian-docs/DOCUMENTATION_INDEX.md(or simply open the Graph View)!
If you don't use Obsidian, you can still read all the Markdown files in the obsidian-docs/ folder directly on GitHub!
- Read CONTRIBUTING.md for the full workflow
- Read styleguide.md for code conventions
- Read architecture.md to understand the codebase
- Check good first issues for beginner-friendly tasks
- Fork, branch, commit, push, and PR — see the PR template
- 🐛 Bug fixes — Report and fix issues
- 📖 Documentation — Improve guides, fix typos, add examples
- ✨ UI & Animations — Polish the cinematic experience
- ♿ Accessibility — Make Birthday Bloom work for everyone
- ⚡ Performance — Keep it smooth on all devices
- 💡 Features — Extend existing systems, don't duplicate them
All contributors are expected to follow our CODE_OF_CONDUCT.md. Please be respectful, inclusive, and constructive.
- React.js Team
- Framer Motion
- Tailwind CSS
- Vite
- Canvas-Confetti
- All the open-source contributors who have made this project possible.
This project is licensed under the MIT License. You are completely free to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software with adequate attribution. Commercial use is permitted, though providing credit and starring the repository is deeply appreciated! See the LICENSE file for more details.
We believe that code is a gift. That's why we made Birthday Bloom open-source and free for everyone. If you've used this to make someone happy, consider "paying it forward" by contributing a new feature or helping another developer in the community.
- Write a blog post or share how you used Birthday Bloom.
- Record a guide or tutorial to help other users.
- Donate to open-source libraries that we depend on (like Framer Motion).
Birthday Bloom comes with a complete open-source operating system to make contributing, maintaining, and collaborating easy.
- Issue Templates — Structured forms for bugs, features, docs improvements, and performance reports
- PR Template — Contributor checklist to ensure quality
- CI Pipeline — Automated lint, typecheck, build, and test on every PR
- Dependabot — Weekly automated dependency updates
- CODEOWNERS — Clear ownership map for the repository
See CHANGELOG.md for the full version history.
This project follows Semantic Versioning. Major releases are tracked in releases and summarized in the changelog.
Birthday Bloom is more than code. It's a bridge between technology and human emotion. Whether you're a developer looking for a cool project or a friend looking to make a surprise, we hope this engine serves you well.
- Star the Repo: Help us reach the top of GitHub Trending!
- Share your Story: Use
#BirthdayBloomon social media. - Contribute: We welcome all PRs.
Birthday Bloom was created and is maintained by Naboraj Sarkar. If you find this project useful or want to support future work, feel free to connect via the contact channels below.
Developed by Naboraj Sarkar. Contributions and improvements are welcome.
Need help, collab, or just want to connect? 👇
- 📧 Email → msg@naborajs.me
- 💬 WhatsApp → Message Me now
- 💬 Telegram → @Nishantsarkar10k
- 🐦 Twitter (X) → @ItsNaborajs
- 📸 Instagram → @naborajs
- 🌐 Website → naborajs.com
- 🐙 GitHub → [github.com/naborajs]
- 🎥 YouTube → Naboraj Sarkar Channel
Thank you to all the incredible people who have contributed to making Birthday Bloom a reality! 🙌