Back to all work
Application
Interactive Wedding Invitation
An invitation that is also the event's website, its RSVP system and its guest list.
- Year
- 2026
- Status
- Live
- Role
- Solo: design, front end, back end, organiser panel.

A four-day wedding in Sicily for several dozen people scattered across Poland. The guests need to know where they are flying, where they are sleeping and what they have to confirm; the couple need to know who is coming and what they cannot eat. Every guest gets their own link, and that is the whole of it: no registration, no password, no account. The address is the identity.
Stack
- React 18
- TypeScript
- Vite
- Tailwind CSS
- Framer Motion
- Express
- SQLite
- Sharp
- Nodemailer
- Spotify API
In practice
- A guest confirms they are coming, says how many of them there will be and what they cannot eat, and can come back and change their mind until the deadline.
- The whole weekend in one place: the schedule, the address with a pin on the map, how to get there and where to sleep, so nobody has to ask the couple.
- Everyone puts songs on the shared playlist, by pasting a Spotify link or typing a title from memory, and sees what the others have suggested.
- Photos go up straight from a phone during the party, and come back out full size, without anybody signing up to anything.
- A question nothing on the page answered goes to the couple by email.
- The couple add guests one at a time or paste the whole list at once, fix a typo where they see it, and send the invitations in one go to everyone still waiting.
- Who has answered, how many are coming in total and every dietary note, exportable as a spreadsheet for the venue.
- One click turns the suggestions into an actual playlist on Spotify.
How it is built
- React 18 and TypeScript on Vite, Tailwind and Framer Motion in front; Node and Express behind, with SQLite through better-sqlite3, Nodemailer for the invitations and Sharp for the thumbnails.
- SQLite rather than a database server: the scale is dozens of records, not millions. One file means no maintenance, a backup is a copy of it, and the driver is synchronous, so there is not a single await around a query.
- A token in the address instead of accounts, because a wedding guest will not open an account to say they are coming. It is only written to the browser once the server has accepted it, so a typo in the link never sticks.
- One source for the words: the invitation text lives in a file that both the page and the email template read, so neither can be changed while the other is forgotten.
- Photographs are served through the API rather than statically. The originals sit outside the public directory and the server makes and caches the WebP thumbnails, so hiding a photo in the panel actually hides it instead of leaving a working direct link.
- Three animated interludes stood still despite correct code: Framer Motion maps x and y onto SVG attributes a group element does not have, so the animation quietly did nothing while the rotations kept working and hid it. All horizontal movement moved to native SMIL.
- Spotify metadata with no registered application: the official API when keys are configured, the Open Graph tags on the track page when they are not, oEmbed as the last resort. It works on first run and improves itself once configured.

