Trinta Outubros: Halloween 30th Birthday Invitation
An interactive, horror-movie-themed party invitation built for guests of all ages. It has a collaborative playlist, a costume picker and an add-to-calendar button.
Context
For my 30th birthday I threw a Halloween costume party and wanted an invitation that felt like an event in itself, not a static image sent over WhatsApp. Many guests were 60 or older, so it had to be just as easy to use for my grandparents as for my friends.
The challenge
Build a cinematic, animation-heavy single-page invitation that still works well for older guests: large readable text, big touch targets, no hover-only interactions and support for reduced motion. It also needed a shared playlist where anyone could suggest and vote on songs. That meant no login, no paid backend and a small bundle.
What was built
- Built with React 19 + TypeScript + Vite and split into 25 reusable components and 9 sections (Hero, Countdown, Dress Code, Poster Wall, Playlist…). Scroll and parallax animations use Motion.
- Documented every component in Storybook (34 stories). Vitest + Playwright render all stories in a headless browser as tests, and the a11y addon runs accessibility checks.
- Collaborative playlist: song search uses the public iTunes Search API and includes 30-second previews. Suggestions are stored in Firestore through its REST API instead of the Firebase SDK, which saved about 100 KB.
- Security with Firestore Rules only: field validation, a vote can only go up by 1, nobody can edit or delete, and submissions close automatically at a set deadline.
- Accessibility for 60+ guests: 18px base text, a persistent "Larger text" toggle, 48–56px buttons with text labels, a fixed bottom navigation bar and one-tap interactions (costume draw, flip poster). It respects prefers-reduced-motion.
- "Add to calendar" for Google and iPhone (.ics) with a reminder one day before.
- Automated deploy to Hostinger with rsync over SSH. The script has a guard so --delete can only affect the /party/ folder.
Outcome
- The whole app ships at about 140 KB of gzipped JS, and the playlist runs on Firebase's free Spark plan, so it costs nothing to host.
- Guests of every age could check the date and location, draw a costume idea and add songs straight from their phones, without logging in or installing anything.
- Every visual component is covered by automated render and accessibility tests through Storybook.
- Publishing a new version takes one command (npm run deploy).
Technologies
React · TypeScript · Vite · Motion · Firebase Firestore · iTunes Search API · Storybook · Vitest · Playwright · CSS Modules
Links
Gallery


Next project: RK Barbearia