Open source · Archived

From the printed card to the door, one code per household.

WeDo is a wedding website with invitations, RSVPs, seating and check-in built in. Each household gets a code on its printed card. Guests scan it to reply for everyone on the invite, the couple seats them at tables, and the same code checks them in on the day.

You’re invited

Alex & Sam

Saturday, 14 November 2026

The Garden Ballroom

34 days to go

Dearest Mr. & Mrs. Jordan Tan,

Together with our families, we joyfully invite you to our wedding.

When

Saturday, 14 November 2026 at 7:00 pm

Where

The Garden Ballroom, Level 3

With gratitude,

Alex Lim & Sam Ong

An invite page — the cover, then a letter addressed to the household.

Invites

A code on every card, and a card for every household.

Each invite groups the guests of one household under a random code. The admin page renders a printable card for it: the template background, a formal addressee line, the code, the reply-by date and a QR code that opens that invite’s page.

The same page suggests the message to send alongside it, so invites can go out by post, by chat app, or both.

  • Codes use an unambiguous 31-character alphabet and a secure random source.
  • Addressee lines follow salutations: “Mr. & Mrs. Jordan Tan, Family”.
  • Card backgrounds are uploaded in settings; a plain card is drawn without one.
Together with their families

Alex & Sam

request the pleasure of the company of

Mr. & Mrs. Jordan Tan, Family

Invite code
K7QM4PXR
RSVP by 31 Oct
QR code linking to the RSVP page
A printable card — addressee, code, reply-by date and QR link.

RSVP

Guests reply for everyone on their invite.

The invite page greets the household by name, then lists its guests with Accepts and Declines beside each. One person answers for all of them, leaves a note for the couple and sends it.

Replies can be changed until the reply-by date, which closes at the end of that day in the event’s time zone rather than the guest’s. Guests see only their own invite: no phone numbers, emails or tables.

  • Every reply is checked on the server: captcha, deadline, and that each guest belongs to that invite.
  • New replies can post to a Slack channel.
  • The agreement, change policy and Q&A are written in Markdown by the couple.

Kindly reply

Will you join us?

Please respond by Saturday, 31 October 2026.

Jordan TanAcceptsDeclines
Mei TanAcceptsDeclines
Kai TanAcceptsDeclines
Can’t wait to celebrate with you!
Send RSVP

🙌 K7QM4PXR has responded

Guests

✅ Jordan ✅ Mei ❌ Kai

Can’t wait to celebrate with you!
The reply form for a three-person invite, and the couple’s Slack notification.

Guests & seating

Replies, tables and the venue’s seating chart in one place.

The dashboard counts who is attending, who has declined and who has yet to reply, and how many have checked in. Guests are assigned to tables from the guest list, which shows each table’s assigned and attending guests against its capacity.

When the plan is settled, it exports as a seating-chart CSV for the venue.

  • VIP tables are marked; children and corsage recipients are flagged per guest.
  • Counts update as replies come in.
  • The wedding date and venue are edited in settings, with a countdown on the dashboard.
Attending
86
of 120 guests
Declined
14
Awaiting reply
20
Checked in
0
Table 1 · VIP
10/10
Table 2 · VIP
9/10
Table 3
10/10
Table 4
7/10
Table 5
8/10
Table 6
4/10
The dashboard’s reply counts, then tables against capacity.

Check-in

At the door, by code, name or QR scan.

The check-in page runs on a phone or tablet at the reception table. Ushers scan the guest’s card or type a code or name, and the invite’s attending guests appear with their tables. Tapping who has arrived checks them in.

Once checked in, the guest sees a thank-you from the couple and, if one is set, a gift QR code.

  • Check-in remembers who has already arrived.
  • Search by name suggests matching guests when the card is left at home.
  • If saving fails, the page says so, so the desk can note it by hand.

Welcome!

Please find your table assignments below

Mr. Jordan Tan (Table 4) 🌺
Mrs. Mei Tan (Table 4)
✅ Check In (2)

We hope you have a splendid time!

Alex & Sam

Check-in for one invite — tables shown, two guests selected.

Look & content

Four looks, and nothing about the wedding in the code.

The site comes in four presets — classic, modern, garden and blush — each with its own type and palette, and an optional accent colour. Names, copy, the Q&A and every photo are edited in settings and stored in the database and Vercel Blob.

That keeps the repository free of anyone’s photos, contact details or payment codes, so it can be forked as it is.

  • Photos are resized in the browser before upload, so camera images fit.
  • Uploaded images are type- and size-checked on the server.
  • A test fails the build if photos or phone numbers are committed.

We’re getting married

Alex & Sam

RSVP
classic

We’re getting married

Alex & Sam

RSVP
modern

We’re getting married

Alex & Sam

RSVP
garden

We’re getting married

Alex & Sam

RSVP
blush
The four presets. This page follows whichever one the site uses.

After the day

The site turns into a thank-you page.

Once the wedding date has passed, the home page becomes a note from the couple with a photo gallery. Tapping a photo opens a full-screen viewer with swipe and arrow-key navigation, and a link can point to the full album.

The switch can be turned off, in which case the original site stays up and links to the thank-you page instead.

  • The note is written in Markdown in settings.
  • Gallery photos upload like cover photos and are served at sized resolutions.
  • Section links drop out of the navigation on the thank-you page.

Thank you

Alex & Sam

Saturday, 14 November 2026

Thank you for celebrating with us. Here are a few of our favourite moments from the day.

Memories

The thank-you page — the couple’s note, then the gallery.

Protection

An invite code opens one invite, and nothing more.

Guest pages load only the fields a guest needs, and every Server Action validates its input before touching the database. Admin access is checked by each page, action and route itself rather than by a shared layout.

Sign-in uses Auth0, and admin access can be limited to a list of verified email addresses.

  • Input is validated with zod; errors returned to guests are generic.
  • Admin Markdown renders without raw HTML, and links and images must be https.
  • Check-in also verifies that each guest belongs to the scanned invite.
// Each step returns a generic error to the guest.
submissionSchema.safeParse(input)
await verifyHCaptcha(captcha)  // fails closed
isRsvpClosed(invite.respondBy, invite.event.startTime, timeZone)
planRsvp(inviteGuestIds, { attending, guestIds })
// ↳ rejects guest ids from other invites

// app/god/guests/export/route.ts
await requireAdmin("/god/guests");
The checks behind every reply, in outline.

Archived

Built for one wedding, kept for anyone who wants it.

WeDo was written in 2022 for a wedding in Singapore, where family ran the check-in desk with it on the day. In 2026 it was rebuilt on Next.js 16, React 19 and Prisma 7, redesigned, and made safe to fork. It is not a hosted service: there is no sign-up, and nothing is sold. To use it, fork the repository and deploy your own copy.

WeDo · © WuCoLaBo · MIT licenceSource