An invitation for a summer wedding: full of flowers, bright colours, and as easy to answer as it is to open.



123
guests, each with their own RSVP
2 days
from first design to live
≈12
misspelled answers on my previous invitation: here they’re picked from a list
01 — THE CHALLENGE
The couple wanted something colourful and summery, with the flowers from their reference card. They also wanted tidy answers: on a previous invitation I designed, about 12 answers came in with misspelled songs or allergies.
So allergies are ticked with a tap, and songs are picked from a list, with title and artist.
As of November 2026, 36 of the 123 guests have already confirmed, and the couple sees every answer neatly in their dashboard.
02 — WALKTHROUGH
They tap the flower and the invitation opens. They add the date to their calendar, check the map and gift list, and RSVP with their allergies and a song.
Names are examples and the venue is blurred.
03 — THE INVITATION
04 — THE COUPLE'S DASHBOARD
The couple see who confirmed, who is pending and who can't come. Each box filters the list.
From there they add or fix guests and see what each one answered.
05 — THE GUEST LIST
Here the couple know who is coming and what each guest asked for, without scanning the whole list.
06 — DESIGN + AI
The invitation is a real website: guests RSVP from their phone and the couple sees the answers in their dashboard. I designed the experience and the illustrations; I built the code with AI (Claude Code) on Next.js and Supabase, reviewing every detail before publishing it.
Behind the watercolours there’s code that looks after the guests: their list can’t be downloaded, the music plays well on iPhone and songs come from a real catalogue. These are real excerpts.
supabase/migrations/0006_name_and_first_surname.sql
create or replace function public.find_guest_by_name(query text)
returns table (id uuid, full_name text, status guest_status)
language sql
stable
security definer
set search_path = public, extensions
as $$
with q as (
select lower(unaccent(btrim(query))) as name
)
select g.id, g.full_name, g.status
from public.guests g, q
where lower(unaccent(btrim(g.full_name))) = q.name
or left(lower(unaccent(btrim(g.full_name))), length(q.name) + 1) = q.name || ' '
order by g.full_name
limit 5;
$$;
grant execute on function public.find_guest_by_name(text) to anon, authenticated;07 — DESIGN DECISIONS
The bride's chosen watercolours, in high resolution so they stay sharp.
Tick-box allergies and songs from a list, so most answers can’t be misspelled.
A first name and one surname are enough to RSVP.
It plays when the flower is tapped and can be paused any time.
— THE BRIDE