Case study — product build, live in production

A whole wedding, running on one link

Designed invitation, guest RSVP and secure photo delivery — a multi-tenant platform a venue can run every wedding on. Built in days, hardened like it took months.

Type

Multi-tenant web app

Stack

Next.js · Supabase · ImageKit

Languages

English + Thai, per wedding

Status

Live, with a full public demo

The brief:
replace the paper trail.

A wedding runs on logistics —
and the logistics still run on chat apps and spreadsheets.

Ask anyone who has organised a wedding what the hard part was and they rarely say the ceremony. It is the guest list. Invitations go out over chat, RSVPs come back as a thumbs-up emoji or not at all, someone keeps a spreadsheet that is out of date the day it is made, and three months after the event the photos are still sitting in a photographer's transfer link that expired last week.

The brief was to put all of that on one link. A guest receives an invitation that looks designed — the couple's names, their colours, their story, the venue and schedule — and on the same page they answer the RSVP. The couple watch responses arrive in a dashboard instead of a group chat. After the wedding, the same link becomes the delivery channel for the real photos, privately, to the people who were actually there.

One more requirement made it a platform rather than a website: it had to be multi-tenant. The economics of a one-off wedding site are terrible — every couple needs one for a single day. But a venue hosts weddings every week. Build it so each wedding is its own tenant with its own guests, its own media and its own settings, and the same build serves every event the venue ever hosts. That is what was built: not a wedding website, but the machine that produces them.

The public demo — Lily & Tan at The Garden House, Bangkok — runs on the production system, bilingual in English and Thai, with a real guest list, real RSVPs and a real gallery. It is not a mock-up; it is tenant number one.

What was built

Three surfaces, one system —
guest, couple, and owner.

The invitation

A page that reads like stationery

Each wedding gets a designed page — monogram, palette, story, schedule, venue — rendered from the couple's own content and colours, not a theme with the names swapped. The demo wedding runs a sage-and-cream identity with a bilingual toggle.

RSVP

Answers that land in a dashboard

Guests respond on the invitation itself — attendance, party size, notes. Responses are tracked per invite, so the couple can see who has answered, who is bringing whom, and who needs a nudge, without keeping a spreadsheet alive by hand.

Photo delivery

The gallery, after the day

When the photographer delivers, the same link becomes the album: a private gallery with downloads for guests. Media is served through signed URLs, so images and videos are only reachable through the platform — a hotlinked address returns nothing.

Phases

One link, two lives

A wedding page has a before and an after. The platform models that as a phase switch — invitation-and-RSVP mode until the day, gallery-and-thanks mode after — flipped manually or on a date, so the link printed on the physical card never changes.

Sign-in

No passwords at a wedding

Guests and couples sign in with a one-time code sent to their email — nothing to create, nothing to forget between the save-the-date and the album. Codes are issued by the auth layer, delivered over a verified sending domain.

The dashboard

Where the owner runs it all

Invites, guests, RSVPs, media, phase and publishing controls per wedding — and because the system is multi-tenant, the venue's operator manages every event from the same place, with each wedding sealed off from the others.

The hard part was not the pages.
It was the walls between them.

Tenancy is a security problem

Multi-tenant means every wedding's guests, RSVPs and photos live in the same database. The walls between weddings have to be real — not "the app doesn't show it," but "the database will not return it."

Enforced at the database

Access rules are row-level security policies in Postgres, not checks in the application. The API layer exposes the database directly, so an app-layer guard is decoration — the policy is the wall, and it holds for every client ever written.

Attacked before launch

The build was audited adversarially: probes for role escalation, cross-tenant writes and shared-row leaks — the classic multi-tenant failure modes. Three real isolation holes were found this way and fixed in the policy layer, not patched in the UI.

Media locked the same way

Photos and videos are served exclusively through signed URLs with enforcement switched on at the CDN — an unsigned request is refused. A wedding album is private by construction, not by obscurity.

From the live demo

Captured from the production system —
not design mock-ups.

The demo wedding's story and schedule sections, in the couple's own palette
Lily & Tan — the invitation reads like stationery, not a template.
The wedding invitation on a phone, where most guests open it
Most guests open the link on a phone — the page is built for that first.

QUESTIONS WORTH ASKING

Yes — the template page embeds the live demo wedding, Lily & Tan at The Garden House, Bangkok. It runs on the production platform with a real guest list, RSVPs and gallery, in English and Thai.

It was built venue-first: a wedding venue or planner runs every event they host on it, each wedding sealed off as its own tenant. It works just as well for a single couple who want their invitation, RSVP and album on one link — the demo wedding is exactly that.

That is the point of the case study. The shape — a branded public page, a private dashboard, secure media, multiple tenants — fits venues, studios, agencies and any business that runs events or clients through a link. Pricing has the real numbers; every project gets a fixed quote before work starts.

Because "the app hides it" is not the same as "the system refuses it." A guest list and a private album are personal data; if the walls between customers are only in the interface, one bug leaks someone's wedding. Enforcing isolation in the database means every path to the data hits the same wall — including paths nobody has built yet.

The build itself took days, not months — modern tooling is genuinely that fast in the right hands. What the schedule did not skip was the hardening: an adversarial security pass over tenancy, roles and media access, with the holes it found fixed at the database layer before anything shipped.

Have a business that runs on events,
clients, or bookings?

This platform started as one sentence in a brief. Send yours — you will get a straight answer and a fixed quote.