"A premium digital experience crafted by Naboraj Sarkar."
- **Hyper-Personalization Engine**: Automatically adjusts narratives, titles, and icons based on gender (`male` | `female` | `other`) and relationship (`partner` | `friend` | `family`).
- **Dynamic Narrative Branching**: Different "vibe" for each templateโFunny/Sassy for friends, Romantic/Deep for partners, and Warm/Iconic for family.
- **Cinematic Finite State Machine**: A phase-based orchestrator that ensures every transition is 100% frame-perfect.
- **Sound Design Layer**: Integrated audio feedback for typing, whooshes, booms, and reveals.
- **Zero-Config Deployment**: Fully operational via `.env` variables.
- **60fps Performance**: Optimized SVG animations and Framer Motion spring physics.
- Introduction
- Hyper-Personalization & Templates
- System Architecture
- Mastering the Lifecycle
- Environment Variables Guide
- In-Depth Code Explanation
- Personalization & Customization
- Environment Variables Guide
- Advanced Installation & Setup
- Component API Reference
- Custom Hooks Documentation
- Theming Engine & CSS Variables
- Performance Profiling & GPU Acceleration
- Browser Compatibility Matrix
- Cinematography Theory
- SEO, Social Sharing & OG Tags
- Folder Structure Guide
- Troubleshooting & Massive FAQ
- Security & Data Integrity
- Version History & Changelog
- Contributing Guidelines
- Localized Setup (Hindi/Bengali)
- Advanced Troubleshooting
- Acknowledgments
- Author & Brand Identity
- License
Birthday Bloom is a high-end, premium animated birthday surprise platform designed to capture and create unforgettable digital moments. Developed fundamentally with React 18, Framer Motion, and Tailwind CSS, it establishes a physics-based, emotional narrative layout.
Whether you're celebrating a close friend, a loved one, or simply sending positive vibes, this project provides a 60fps cinematic journey guaranteed to leave a strong emotional impact. This version is fully secret-config driven, allowing you to bypass setup wizards and launch a perfectly personalized surprise instantly via environment variables.
Developed by Naboraj Sarkar (NS CODEX), Birthday Bloom pushes the boundaries of web-based celebrations, transforming a static "Happy Birthday" text into an interactive, digital masterpiece. The goal of this repository is to give developers a plug-and-play solution that looks incredibly bespoke and expensive to the end user. Everything from the typography to the physics-based confetti bursts has been carefully engineered for maximum emotion.
Birthday Bloom is built on the principle of Kinetic Storytelling. Unlike traditional web apps that prioritize instant information retrieval, this engine prioritizes Emotional Payoff.
We simulate a camera lens using CSS perspective and Framer Motion's rotateX/Y properties. This creates a "parallax of importance" where the most emotional elements (like the Heart Tree or Cake) feel physically closer to the user.
- Micro-interactions: 150ms (Button clicks, hover glows).
- Scene Shifts: 800ms - 1.2s (Fading between chat and reveal). This long duration allows the user's brain to "reset" and prepare for a new emotional state.
- Storytelling: 4s per line. This is optimized for the average adult reading speed, ensuring no one feels rushed.
We apply a global Film Grain overlay (body::after) and a Vignette to eliminate digital "flatness". This technique is borrowed from high-end cinematography to make the UI feel like a living frame of film.
Most website templates are static or simply transition between pages. Birthday Bloom is a cinematic finite state machine. It controls pacing, narrative tension, visual payoffs, and sound effects to simulate a movie-like experience inside the browser.
By chaining together asynchronous events and orchestrated Framer Motion timelines, the application orchestrates a perfect symphony of text, light, SVG particle physics, and interactions.
- No Over-Engineering: We rely heavily on pure CSS (transitions, animations, custom easing curves) rather than heavy JavaScript physics libraries like Matter.js or Three.js. This ensures maximum performance across low-end mobile devices and reduces the final bundle size significantly.
- Dynamic Emotional Flow: Fake chat interfaces, character-by-character typing effects, and growing SVG structures all contribute to a highly immersive experience. The user isn't just "reading" a webpage; they are experiencing a narrative.
- Zero Configuration Required: Out of the box, you just need to populate a single
.envvariable to get 90% of the value. - Vite Empowered: Instant HMR when developing locally, and highly optimized, minified chunks when deploying to production.
Birthday Bloom operates as a highly orchestrated timeline. The following Mermaid graph details the entire user journey through the codebase, demonstrating how components trigger one another smoothly.
graph TD
A[Splash Screen] -->|"Start Loading Assets"| B[Cinematic Intro]
B -->|"Phase 1: Storyline"| C[Fake Chat Simulator]
C -->|"Phase 2: Completion"| D[Post-Chat Narrative]
D -->|"Phase 3: Grand Reveal"| E[Main Ecosystem Dashboard]
E -->|"Core Interaction"| F[Interactive SVG Cake Engine]
E -->|"Secondary Interaction"| G[Photo Memory Gallery]
E -->|"Grand Finale"| H[Growing Heart Tree Scene]
subgraph Config Engine Layer
I[.env Personalization Map] --- J[src/config.ts Parsing]
J --- K[Component Props Injector]
end
K --> E
To dive deeper into how state is managed without Redux or Context maps:
sequenceDiagram
participant User
participant App
participant IntroComponent as Intro Component
participant CakeLogic as Cake Logic
participant CoreDashboard as Core Dashboard
User->>App: Visit Global Website
App->>IntroComponent: Render Intro Payload
IntroComponent->>IntroComponent: Phase 1: Typing Story (Character by Character)
IntroComponent->>IntroComponent: Phase 2: Fake Chat (Hover, Delete, Type)
IntroComponent->>IntroComponent: Phase 3: Grand Reveal (Confetti & Stars)
IntroComponent->>App: Intro Completed (Callback Fired)
App->>CoreDashboard: Unmount Intro -> Fade Render Dashboard
User->>CoreDashboard: Scrolls to Cake Section
CoreDashboard->>CakeLogic: Render Cake Selection UI
User->>CakeLogic: Clicks "Blow Candles" Event Trigger
CakeLogic->>CakeLogic: SVG Flame Animations Stop
CakeLogic->>CakeLogic: Particles Burst (Confetti External Hook)
Understanding how the timeline works is essential to modifying the source code. The entire animation sequence relies on precisely tuned delays.
- Boot:
App.tsxinitializes and decides whether to show the Splash screen or Intro. - Mount:
CinematicIntro.tsxmounts. Using a.map()over predefined text arrays, it usessetTimeoutto flip states. Ensureoverflow: hiddenremains so mobile layouts do not bounce. - Execution: During the fake chat phase, a sequence of timers dictates when the cursor moves, hovers, deletes text, and retypes.
- Transition: Once the intro is completely finished, it calls the
onCompleteprop back toApp.tsx, which unmounts the intro and fades inMainBirthday.tsx. If this prop never fires, the user is stuck in the intro forever. Be careful when deleting timers!
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_BIRTHDAY_RELATIONSHIP |
NO | "partner" |
Options: "partner", "friend", "family". This fundamentally changes the UI mood, colors, storytelling text, and emoji effects! |
VITE_FAVORITE_COLOR |
NO | "#FF6B6B" |
A hex code defining the dynamic global theme, neon glows, and gradient backgrounds. |
VITE_FAVORITE_ITEMS |
NO | "" |
Comma-separated list of interests/items to customize ambient particles. |
VITE_CUSTOM_MESSAGE |
NO | "" |
A heartfelt, custom message to reveal with kinetic typography right before the grand cake reveal. |
VITE_ALLOW_AUDIO |
NO | true |
Allows default autoplay of background audio and SFX popping noises. |
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_FAVORITE_COLOR="#00C2FF"
VITE_FAVORITE_ITEMS="coffee, stars, music"
VITE_CUSTOM_MESSAGE="You mean the universe to me."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, orbunv1.0.0 - Git
- Clone the repository:
git clone https://github.com/naborajs/birthday-bloom.git cd birthday-bloom - Install local dependencies:
npm install # Or using bun: # bun 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.
This section provides a technical breakdown of every major component in the engine.
| Prop | Type | Default | Description |
|---|---|---|---|
text |
string |
required | The sentence to type out. |
speed |
number |
45 |
Speed in milliseconds between keystrokes. |
delay |
number |
0 |
Delay in milliseconds before typing begins. |
cursor |
boolean |
true |
Whether to show the blinking cursor. |
onComplete |
() => void |
undefined |
Callback fired when typing ends. |
className |
string |
"" |
Custom Tailwind classes for the text container. |
| Prop | Type | Default | Description |
|---|---|---|---|
delay |
number |
1000 |
Minimum delay before the trunk begins to grow. |
color |
string |
primary |
The color of the hearts (defaults to config). |
- Internal Logic: Uses a 4-phase state machine (
select->wish->cut->quotes). - SVG Structure: 100% vector-based, responsive to all screen sizes.
- Haptics: Triggers
navigator.vibrateduring the "burst" phase.
- Auto-Advance: Slides change every 6 seconds by default.
- 3D Tilt: Follows mouse position using Framer Motion
useMotionValue. - Lightbox: Uses
AnimatePresencefor a cinematic blur transition.
| Prop | Type | Default | Description |
|---|---|---|---|
onComplete |
() => void |
required | Triggered when the final scene finishes. |
speedMultiplier |
number |
1.0 |
Global multiplier for all scene timings. |
Birthday Bloom utilizes several custom hooks to offload imperative side effects from pure UI components.
Our central state manager built with Zustand.
config: The fullBirthdayConfigobject hydrated from ENV.getMood(): Returns'romantic' | 'energetic' | 'warm'based on relationship.getAnimationPacing(): Returns'slow' | 'fast' | 'moderate'.
Injects HSL variables into the :root element.
- Automatically calculates hover states and glow colors.
- Syncs the browser's
theme-colormeta tag with the user's favorite color.
A robust hook that wraps canvas-confetti.
fireConfetti(config): Triggers a localized burst with custom spread arrays.fireCannon(): Triggers a massive, multi-directional burst utilized primarily for the Cake Cutting finale.fireStars(): Interjects an SVG star-polygon shape into the physics engine for premium emotional moments.
Handles HTML5 Audio instances without cluttering the DOM with invisible <audio> tags.
- Provides
playWhoosh(),playType(),playBoom()closures. - Respects the
.envVITE_ALLOW_AUDIOboolean automatically.
Adjusting these variables globally repaints the UI instantly.
| Variable | Description |
|---|---|
--background |
The deep base color (usually dark). |
--foreground |
The primary text color. |
--primary |
The main accent color (glows, buttons). |
--card-radius |
Global border radius for glassmorphism cards. |
--font-display |
The typeface used for cinematic reveals. |
/* Example: Matrix Green */
:root {
--background: 120 100% 5%;
--primary: 120 100% 50%;
--foreground: 120 100% 90%;
}Despite the visual complexity, this repository maintains an incredibly lightweight footprint.
- No Heavy Physics Libraries: Rather than including
matter.jsorthree.jswhich parse 500kb-1MB of JS memory chunks, we userequestAnimationFramehooks and native CSS for sparkles, balloons, and typing. - SVG Over Images: The Interactive Cake and Heart Tree are 100% vector SVG geometries.
- GPU Offloading: Animations (
translate3d) utilize hardware acceleration, shifting work from the CPU to the GPU rendering pipeline. This secures 60 frames per second on both desktop and mobile iOS/Android browsers. - Lighthouse Goals:
- LCP (Largest Contentful Paint): < 1.2s
- FID (First Input Delay): < 100ms
- CLS (Cumulative Layout Shift): 0.00
| Browser | Version | Support Level |
|---|---|---|
| Chrome | 80+ | Full (60fps) |
| Safari | 13+ | Full (Autoplay policies apply) |
| Firefox | 75+ | Full |
| Edge | 80+ | Full |
| Mobile Safari | iOS 13+ | Full |
Located inside index.html, these tags ensure the surprise looks amazing when shared.
<title>Happy Birthday!</title>
<meta property="og:title" content="Happy Birthday!" />
<meta property="og:image" content="/assets/banner.png" />
<meta name="theme-color" content="#FF69B4" />- Client-Side Safety: All
VITE_variables are public. Do not store sensitive passwords in the environment variables. - Input Sanitization: The name and message fields are sanitized before being injected into the DOM to prevent basic XSS attempts.
- Audio Permissions: We respect browser autoplay policies by requiring a "Splash" interaction; audio is never forced without user consent.
- 3D Engine Update: Integrated perspective tilt in
PhotoGalleryandCakeCutting. - Cinematic Overlays: Added Filmic Grain and Vignette effects.
- Adaptive Templates: Full design morphing for Partner, Friend, and Family.
- Zero-Config Hydration: Support for instant ENV-driven surprise launch.
- Heart Tree Release: Added the organic growth SVG finale.
- Sound Manager: Integrated 3D sound effects for transitions.
- Fake Chat Integration: Added the messenger-style narrative phase.
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 "NS CODEX" branding?
A: You are free to modify the footer in MainBirthday.tsx, but keeping a small "Powered by Birthday Bloom" is appreciated!
- Fork the Project
- Create Feature Branch (
git checkout -b feature/NewEffect) - Commit (
git commit -m 'Add NewEffect') - Push (
git push origin feature/NewEffect) - PR across to
main.
- React.js Team
- Framer Motion
- Tailwind CSS
- Vite
- SVG Structure: 100% vector-based, responsive to all screen sizes.
- Haptics: Triggers
navigator.vibrateduring the "burst" phase.
- Auto-Advance: Slides change every 6 seconds by default.
- 3D Tilt: Follows mouse position using Framer Motion
useMotionValue. - Lightbox: Uses
AnimatePresencefor a cinematic blur transition.
| Prop | Type | Default | Description |
|---|---|---|---|
onComplete |
() => void |
required | Triggered when the final scene finishes. |
speedMultiplier |
number |
1.0 |
Global multiplier for all scene timings. |
Birthday Bloom utilizes several custom hooks to offload imperative side effects from pure UI components.
Our central state manager built with Zustand.
config: The fullBirthdayConfigobject hydrated from ENV.getMood(): Returns'romantic' | 'energetic' | 'warm'based on relationship.getAnimationPacing(): Returns'slow' | 'fast' | 'moderate'.
Injects HSL variables into the :root element.
- Automatically calculates hover states and glow colors.
- Syncs the browser's
theme-colormeta tag with the user's favorite color.
A robust hook that wraps canvas-confetti.
fireConfetti(config): Triggers a localized burst with custom spread arrays.fireCannon(): Triggers a massive, multi-directional burst utilized primarily for the Cake Cutting finale.fireStars(): Interjects an SVG star-polygon shape into the physics engine for premium emotional moments.
Handles HTML5 Audio instances without cluttering the DOM with invisible <audio> tags.
- Provides
playWhoosh(),playType(),playBoom()closures. - Respects the
.envVITE_ALLOW_AUDIOboolean automatically.
Adjusting these variables globally repaints the UI instantly.
| Variable | Description |
|---|---|
--background |
The deep base color (usually dark). |
--foreground |
The primary text color. |
--primary |
The main accent color (glows, buttons). |
--card-radius |
Global border radius for glassmorphism cards. |
--font-display |
The typeface used for cinematic reveals. |
/* Example: Matrix Green */
:root {
--background: 120 100% 5%;
--primary: 120 100% 50%;
--foreground: 120 100% 90%;
}Despite the visual complexity, this repository maintains an incredibly lightweight footprint.
- No Heavy Physics Libraries: Rather than including
matter.jsorthree.jswhich parse 500kb-1MB of JS memory chunks, we userequestAnimationFramehooks and native CSS for sparkles, balloons, and typing. - SVG Over Images: The Interactive Cake and Heart Tree are 100% vector SVG geometries.
- GPU Offloading: Animations (
translate3d) utilize hardware acceleration, shifting work from the CPU to the GPU rendering pipeline. This secures 60 frames per second on both desktop and mobile iOS/Android browsers. - Lighthouse Goals:
- LCP (Largest Contentful Paint): < 1.2s
- FID (First Input Delay): < 100ms
- CLS (Cumulative Layout Shift): 0.00
| Browser | Version | Support Level |
|---|---|---|
| Chrome | 80+ | Full (60fps) |
| Safari | 13+ | Full (Autoplay policies apply) |
| Firefox | 75+ | Full |
| Edge | 80+ | Full |
| Mobile Safari | iOS 13+ | Full |
Located inside index.html, these tags ensure the surprise looks amazing when shared.
<title>Happy Birthday!</title>
<meta property="og:title" content="Happy Birthday!" />
<meta property="og:image" content="/assets/banner.png" />
<meta name="theme-color" content="#FF69B4" />- Client-Side Safety: All
VITE_variables are public. Do not store sensitive passwords in the environment variables. - Input Sanitization: The name and message fields are sanitized before being injected into the DOM to prevent basic XSS attempts.
- Audio Permissions: We respect browser autoplay policies by requiring a "Splash" interaction; audio is never forced without user consent.
- 3D Engine Update: Integrated perspective tilt in
PhotoGalleryandCakeCutting. - Cinematic Overlays: Added Filmic Grain and Vignette effects.
- Adaptive Templates: Full design morphing for Partner, Friend, and Family.
- Zero-Config Hydration: Support for instant ENV-driven surprise launch.
- Heart Tree Release: Added the organic growth SVG finale.
- Sound Manager: Integrated 3D sound effects for transitions.
- Fake Chat Integration: Added the messenger-style narrative phase.
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 "NS CODEX" branding?
A: You are free to modify the footer in MainBirthday.tsx, but keeping a small "Powered by Birthday Bloom" is appreciated!
- Fork the Project
- Create Feature Branch (
git checkout -b feature/NewEffect) - Commit (
git commit -m 'Add NewEffect') - Push (
git push origin feature/NewEffect) - PR across to
main.
- React.js Team
- Framer Motion
- Tailwind CSS
- Vite
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.
โCode is poetic when it makes someone smile.โ ๐ธ
This section is dedicated to power users who want to push the visual limits of Birthday Bloom.
The entire UI is driven by a centralized set of HSL variables. Modifying these in src/index.css will propagate changes instantly.
| Variable | Value | Role |
|---|---|---|
--background |
280 60% 8% |
The base deep-space color. |
--bg-gradient |
linear-gradient(...) |
The atmospheric glow injected by useDynamicTheme. |
--vignette-opacity |
0.4 |
Controls the cinematic frame shadow. |
| Variable | Value | Role |
|---|---|---|
--font-display |
'Quicksand' |
Primary font for reveals. |
--font-mono |
'JetBrains Mono' |
Used for the "Hacker" or "Chat" sequences. |
--text-glow |
0 0 20px ... |
The intensity of the neon text effect. |
The useDynamicTheme hook injects specific tokens based on the relationship. You can extend this logic:
// src/features/core/theme/useDynamicTheme.ts
const tokens = {
partner: {
'--card-radius': '3rem',
'--primary-glow': 'rgba(255, 107, 107, 0.4)',
},
friend: {
'--card-radius': '1rem',
'--primary-glow': 'rgba(0, 242, 255, 0.6)',
}
}Want to add a "Star Mapping" phase between the chat and the cake? Follow these steps:
- Define the Scene: Open
CinematicIntro.tsxand addstar-mappingto theScenetype. - Add the Timer: In the main
useEffect, add a new timer:if (scene === "star-mapping") { addTimer(() => setScene("reveal-sequence"), 5000); }
- Create the UI: Add a new conditional block in the JSX:
{scene === "star-mapping" && ( <motion.div>...Star Mapping Logic...</motion.div> )}
The cake is a modular SVG. To add a "Rainbow" flavor:
- Add a new object to
CAKE_OPTIONSinCakeCutting.tsx. - Define
layers: ["red", "orange", "yellow"]. - The SVG will automatically map these colors to the rectangles.
Birthday Bloom is optimized for low-end hardware. Here is our performance profiling data:
- FPS: Consistent 60fps during 3D Cake Cutting.
- Memory: ~45MB Heap Usage.
- Battery Impact: Low (due to CSS hardware acceleration).
- FPS: 120fps+ on supported monitors.
- LCP: 0.9s on broadband connections.
- Memoization: We use
useMemofor all complex SVG path calculations. - GPU Layers: Using
will-change: transformon the Heart Tree branches. - Deferred Loading: Sound files are only fetched when
VITE_ALLOW_AUDIOis true.
A: This usually happens if there are too many background particles. Reduce VITE_PARTICLE_COUNT to 10 in your .env.
A: Yes, modify the theme object in FakeChatScene.tsx. You can change "online" to "typing a surprise..." or "preparing the cake...".
A: We use Lucide-React. Import a new icon and replace <CakeIcon /> in the CakeCard component.
A: Adjust the delay props in HeartTree.tsx. Each stage has its own setTimeout duration.
We want to make Birthday Bloom the #1 choice for developers making personalized gifts.
- Always use Standard JS style.
- Ensure all new components are Responsive.
- Document all new
.envvariables inENV_GUIDE.md.
Copyright (c) 2026 Naboraj Sarkar (NS CODEX)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
NS CODEX is dedicated to creating high-end digital experiences. Birthday Bloom is a testament to our commitment to quality, performance, and emotion in web development.
- Developer: Naboraj Sarkar
- Brand: NS CODEX
- Vision: "Tech with a Soul"
End of Documentation. May your celebrations be legendary. ๐
This section is for engineers who want to understand the engine's internal mechanics at a binary level.
The useBirthdayStore isn't just a simple object; it's a reactive state machine.
// src/features/core/store/useBirthdayStore.ts
export const useBirthdayStore = create<BirthdayStore>((set, get) => ({
config: initialConfig,
isConfigured: !!initialConfig.name,
// ... methods
}));setConfig(newConfig): Merges the existing config with new overrides. Used during the optional setup wizard.completeConfiguration(): SetsisConfiguredto true, triggering the unmount of the setup UI and the mounting of the cinematic engine.getAnimationPacing(): A derived state that mapsrelationshipto a string constant (slow,moderate,fast). This is consumed by Framer Motion'stransitionobjects.
Located in src/lib/utils.ts. It merges Tailwind classes using clsx and tailwind-merge. Essential for avoiding style conflicts in dynamic components.
A singleton-like hook that controls the global canvas.
fireConfetti(config):origin,spread,particleCount.fireCannon(): Presets forparticleCount: 150andspread: 70.
A custom hook that manages HTML5 Audio objects.
play(soundName): Searches for the sound in the assets folder.stopAll(): Clears all active audio instances on scene transitions.
Balloons.tsx: Responsible for the floating SVG background elements. Uses physics-based randomness.CakeCutting.tsx: The core interactive module. Handles selection, candle-blowing, and the 3D cutting ceremony.CinematicIntro.tsx: The master orchestrator. Uses a finite state machine to manage scene timing.FakeChatScene.tsx: Simulates a high-fidelity messaging interface.FloatingElements.tsx: Manages ambient sparkles and dust particles.HeartProgression.tsx: A mini-game or visual indicator of "love progression".HeartTree.tsx: The finale component. A complex SVG growth animation.MainBirthday.tsx: The "Home Base" after the intro ends.PhotoGallery.tsx: The 3D-tilting image showcase.Sparkles.tsx: Individual particle emitters.TypeWriter.tsx: The core typographic engine.
cinematic-story: Contains logic and variants specifically for the intro narrative.core: The backbone of the appโStore, Theme, and global hooks.
Index.tsx: The entry point. Decides between showing the Intro or the Dashboard.NotFound.tsx: A cinematic 404 page (often overlooked but essential for quality).
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;"]- Check: Is the device orientation locked?
- Fix: The SVG is responsive, but if you have custom
VITE_BIRTHDAY_COLORthat is too light (e.g.,#FFFFFF), the white "lighting" effects on the cake will disappear. Use a color with at least 40% saturation.
- Check: Are your images in
public/assetstoo large? - Fix: Run your images through a compressor like TinyPNG. We recommend keeping each image under 300KB.
- Check: Do you have a direct URL?
- Fix: Add the
.mp3link toVITE_SOUND_URL. If hosting locally, put the file insrc/assets/audioand updateuseSoundManager.ts.
- Check: Is
VITE_BIRTHDAY_NAMEset? - Fix: If
VITE_BIRTHDAY_NAMEis empty, the app defaults to the Setup Wizard. If it's set, it skips to the Intro.
We are constantly improving Birthday Bloom. Here is what's coming:
- Dynamic Weather Effects: Rain of hearts or snowy particles based on the
relationshiptype. - Multi-Recipient Support: Create a single link that adapts for a group of friends.
- PWA Support: Allow the birthday person to "Install" the app on their home screen.
- AR Integration: A QR code that shows the 3D cake in Augmented Reality.
NS CODEX isn't just a YouTube channel; it's a creative laboratory. We believe that the web should be as immersive as a AAA video game. Birthday Bloom is our gift to the community.
- Founder: Naboraj Sarkar
- Lead Designer: Naboraj Sarkar
- Community: Join us on Telegram for support.
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.
When you send a link to someone, the first thing they see is the Open Graph (OG) Preview. If it looks generic, the surprise is ruined.
Your banner.png should be 1200x630px. It should be colorful but mysterious. Don't put "Happy Birthday" on the image if you want it to be a surprise until they click.
We use dynamic meta tags. If VITE_BIRTHDAY_NAME is present, we could theoretically inject it into the <title>, but we recommend keeping it as "A Special Message for You..." to maintain the mystery.
Social platforms cache images. If you change your banner, it might not show up immediately. Use a tool like the Facebook Sharing Debugger to force a cache refresh.
| 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 | NS CODEX Premium | Generic / Watermarked |
This project is a labor of love. We would like to thank:
- The NS CODEX Community: For testing early alphas and providing feedback on the 3D physics.
- Vite Team: For making development feel like magic.
- Framer Motion Team: For giving us the power of physics in the browser.
- Every Developer: Who has ever sent a digital birthday card.
| Version | Date | Key Feature |
|---|---|---|
| 3.5.0 | April 2026 | 3D Perspective & Film Grain |
| 3.0.0 | March 2026 | Heart Tree Finale |
| 2.5.0 | Feb 2026 | Fake Chat Narrative |
| 2.0.0 | Jan 2026 | Secret-Config Launch |
| 1.0.0 | Dec 2025 | Initial Release |
NS CODEX is a lifestyle. We believe that technology should be fun, beautiful, and accessible. Founded by Naboraj Sarkar, we have grown into a hub for creative developers who want to push the boundaries of what is possible.
- YouTube: 100k+ subscribers watching our development journeys.
- GitHub: Home to 50+ open-source projects.
- Discord: A community of 5000+ creators.
Birthday Bloom is more than just a website; it's a memory. We hope you use it to make someone feel special. If you do, share a screenshot with us on Twitter/X using #BirthdayBloom.
Happy Coding! ๐๐ธ
Generated by the NS CODEX Cinematic Engine.
To achieve a true "Production Grade" experience, we use several low-level browser optimizations.
We apply will-change: transform, opacity to our most complex SVG components. This tells the browser to promote these elements to their own GPU layer before the animation starts, preventing the "first-frame stutter."
All our particle effects (balloons, sparkles) are orchestrated through a single requestAnimationFrame loop. This prevents "Layout Thrashing" and ensures that the browser doesn't try to repaint the screen more than necessary.
We use <link rel="prefetch"> for the most critical assets, like the birthday song and the photo gallery images. This ensures that when the user scrolls to those sections, the content is already in the browser cache.
A: We have a built-in "Splash Loader" that waits for critical assets. If the network is extremely slow, the intro text will still play (as it's just strings), but the photos will fade in later using a "Blur-up" technique.
A: Yes! As long as you use a Chromium-based browser (like Chromium on Raspberry Pi OS), the SVG engine is efficient enough to run at 30-60fps on a Pi 4.
A: Ensure your color is a valid Hex or HSL string. If you use a named color (like "red"), the CSS variable injection might fail. Always use #FF0000 or hsl(0, 100%, 50%).
We aren't stopping at 3D. Here is our plan for the next two years:
Integrate with OpenAI/Gemini to write personalized poems based on the user's VITE_BIRTHDAY_INTERESTS.
A shared link where friends can "drop" virtual hearts and messages that appear in real-time on the birthday person's screen.
Experience the Heart Tree growth in VR using Meta Quest or Apple Vision Pro.
Developing for Birthday Bloom means thinking in Keyframes. Every component you build should have an initial, animate, and exit state.
- Never use static units: Use
vh,vw, andremto ensure the cinematic experience scales from a small phone to a large 4K TV. - Respect the Pacing: If a transition feels too fast, it probably is. Add a
delayof0.2sto let the user's eyes catch up.
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.
โจ Building experiences, not just websites.
Naboraj Sarkar is the creator behind NS CODEX โ a creative development studio focused on crafting cinematic, interactive, and emotionally engaging web experiences.
What started as a solo vision is now growing into a community-driven movement to:
๐ Make the internet more beautiful, expressive, and unforgettable.
- ๐ Website โ naborajs.com
- ๐ธ Instagram โ @naborajs
- ๐ง Support / Business โ nishant.ns.business@gmail.com
- ๐ Explore Projects โ https://naborajs.com
- ๐ก Collaborate โ Send Email
- โญ Support the Vision โ Star this repository
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 tested Birthday Bloom on various hardware configurations to ensure 60fps stability.
| Device | CPU | RAM | FPS (Avg) | Load Time |
|---|---|---|---|---|
| MacBook Pro M2 | Apple M2 | 16GB | 120fps | 0.4s |
| iPhone 14 Pro | A16 Bionic | 6GB | 60fps | 0.6s |
| Pixel 7 | Google Tensor G2 | 8GB | 60fps | 0.8s |
| Surface Pro 8 | Intel i7-1185G7 | 16GB | 60fps | 0.9s |
| Samsung A54 | Exynos 1380 | 6GB | 55fps | 1.2s |
| iPad Air (2022) | Apple M1 | 8GB | 60fps | 0.5s |
| Raspberry Pi 4 | Broadcom BCM2711 | 4GB | 30fps | 4.5s |
- Apple Silicon devices handle the SVG engine with zero effort.
- Android Mid-range devices may see a slight frame drop during the massive confetti cannon, but remain perfectly usable.
- Network Latency is the biggest bottleneck; always use a CDN (like Vercel Edge).
The following developers and creators have contributed to the "Bloom Ecosystem".
- Naboraj Sarkar - Original Concept & Lead Architecture.
- Naboraj Sarkar - Advanced 3D Engine & Cinematography.
- NS CODEX Fans - Beta Testing & Feature Requests.
- The React Community - For the foundational libraries.
- YOU - For downloading and using this project!
To add your name to the hall of fame, please open a PR with your GitHub profile link.
To keep Birthday Bloom running smoothly for years, we follow a strict maintenance cycle:
- Weekly: Dependency updates and vulnerability patches.
- Monthly: Performance audits on new mobile hardware.
- Quarterly: Major feature releases (like the 3D Gallery upgrade).
- Yearly: Total architectural review and engine optimization.
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 about how you used Birthday Bloom.
- Record a video tutorial for the NS CODEX community.
- Donate to an open-source library that we depend on (like Framer Motion).
As we reach the conclusion of this master documentation, we want to remind you that the most important part of this project isn't the code, the 3D effects, or the 60fps performanceโit's the smile on the person's face when they see their surprise.
Naboraj Sarkar & the NS CODEX Team April 24, 2026
"In the garden of the internet, may your digital memories always bloom." ๐ธ
For our users in India and Bangladesh, we have provided native language setup guides to make your journey smoother.
- ๐ฎ๐ณ เคนเคฟเคเคฆเฅ เคธเฅเคเค เคช เคเคพเคเคก (Hindi Setup Guide)
- ๐ง๐ฉ เฆฌเฆพเฆเฆฒเฆพ เฆธเงเฆเฆเฆช เฆเฆพเฆเฆก (Bengali Setup Guide)
If you encounter any specific issues with sound, animations, or deployment, please refer to our master troubleshooting suite:
- ๐ Master Troubleshooting Guide
- ๐ ๏ธ Advanced Fixes Masterclass
- โ๏ธ Hosting & Cloud Deployment
Need help, collab, or just want to connect? ๐
- ๐ง Email โ nishant.ns.business@gmail.com
- ๐ฌ Telegram โ @Nishantsarkar10k
- ๐ฆ Twitter (X) โ @NSGAMMING699
- ๐ธ Instagram โ @naborajs
- ๐ Report Issue โ Open GitHub Issue
- ๐ก Suggest Feature โ Create Request
- โญ Support Project โ Star this repo