The Armour Wedding
RSVPs, menu choices, song requests and shared photos — a platform for our own wedding
- No application server — the browser is the backend
- Scan a table card, land in the photo uploader
- Real RSVPs from real guests, in two languages
We got married in May 2026, and the whole run-up went through a site I built for it: the invitation, who was coming, what each of them wanted to eat, the songs they wanted played, and — on the day itself — the photos they took. Guests come in English and Polish, so it shipped in both. The site is retired now that the day has passed; the screenshots here come from a local copy seeded with fictional guests.
The constraint I set was that one person should be able to run it with almost no server to maintain. A single small Lambda handles the password gate; everything else is the browser talking straight to managed services.

No server, just the browser and managed pieces
There is no application backend. The Vue SPA reads and writes Supabase — Postgres with an auto-generated REST layer — directly from the client for everything relational: parties, guests, menu, songs. Photos go to AWS S3, with the browser getting temporary upload credentials from a Cognito Identity Pool rather than a presign endpoint I'd have to run. Song search hits the Spotify Web API. The one gate — the password on the private pages — is an AWS Lambda behind a Function URL. The whole thing is served as a static build from AWS Amplify Hosting.
That shape is the point: it's cheap, it deploys as static files, and there's no server process to keep alive for a site that only had to survive a few months of real traffic.
The RSVP
Every guest belongs to a party with a short code. Enter the code — or arrive on a link that carries it — and the app loads that party and its people, and asks each of them, individually, for a starter, a main and a dessert. Children get their own path: a half-sized adult portion or a set kids' menu.

Song requests are part of the same flow. A search box queries Spotify live from the browser, and the chosen track travels with the RSVP so it lands in the same place as everything else.

Behind it, a password-gated dashboard reads every party and guest and aggregates it entirely on the client into the numbers a caterer actually needs: who's confirmed, and how many of each dish to cook.

A QR code that's really a magic link
The physical-to-digital bridge is my favourite part. Each printed code encodes a URL rather than an
id. A guest's card carries a link that deep-links straight to their own prefilled RSVP — the
same ?code= the form reads, so scanning it skips the code entry entirely.
The photos card goes one better. Its code encodes …/photos?password=…&lang=…, and the router
treats a ?password= in the URL as an instruction to unlock. So a guest scans the card on the table,
and lands directly in the unlocked, correct-language photo uploader — no code, no password prompt,
nothing to type. The codes themselves are drawn with qr-code-styling, rounded and centred on our
initials.

Uploading the day
The photos page lets guests upload straight from their phones. Because the browser holds Cognito
credentials, each file goes directly to S3 with no upload server in the middle. There's an
in-browser camera too, capturing video with a MediaRecorder codec fallback chain (VP9, then WebM,
then MP4) so it works across the phones people actually brought.

Everything lands in a shared gallery with a lightbox. Downloading uses the Web Share API where a phone supports it, with a fallback that staggers the downloads one second apart — because Android Chrome quietly blocks a burst of simultaneous ones.
Two languages
It was a UK–Polish wedding, so there are two full editions — English and Polish — sharing one
Supabase project. The Polish site is the same RSVP over the same guest data, reading its own
menu_items_pl table so the courses come through translated.

What I'd change
Two things, both from hindsight rather than regret.
The Polish edition should have been proper localisation inside one codebase, not a second repository.
Forking it was simply faster under a fixed date, and the cost showed up later as two builds to keep
in step by hand — exactly what an i18n layer and a single deploy would have removed.
And the RSVP submit writes one guest at a time in a loop. It's fine at a wedding's scale, but it's a batched upsert wearing the wrong clothes: one round trip would be correct where several do the job today.