Dinner parties don't scale the way most social products expect them to. A host isn't broadcasting to followers — they're vouching for specific people around a specific table. We built the software layer underneath that relationship: a place where a host can put together a dinner and invite people to it, where guests can ask to join a dinner they weren't personally invited to, and where the guest → member → host relationship is actively managed by the product instead of sorted out by hand.

The instinct on a project like this is to reach for a single role enum — guest, member, admin, pick one. We didn't do that, because it doesn't match how the club actually works.
Whether someone has paid to join the club, whether they're trusted to host, and whether they administer the platform are three independent facts about a person — conflating them would have meant either over-privileging people or building awkward workarounds the moment reality didn't fit the enum.
That model is what lets the product say something different to five different people looking at the exact same dinner: a guest who hasn't been invited into the club sees an explanation and a path forward instead of a locked door; a confirmed guest sees the full address only once they're actually coming; a host sees an "Edit Dinner" button where a guest sees "Join the Table."
Progressive disclosure of the address — the exact address is withheld until an RSVP is confirmed or the viewer is the host/co-host; before that, guests see only the neighborhood.
Time-boxed guest visibility — fellow guests' names stay private until 48 hours before the dinner, so a "who's going to be there" browse doesn't turn into a directory.
Per-dinner co-hosting — instead of a global "host" bit, co-host trust is scoped to the one dinner it was granted for, so a member can be handed real responsibility for a single event without the entire host toolkit.
An admin-only visibility control — the dinner-creation form changes shape for admins, exposing a private/members-only toggle that regular hosts never see.

Membership isn't a fixed-tier subscription — it's pay-what-you-want, from free up to a $50/month ceiling, set with a single slider. That one decision rippled through the entire payment integration: instead of a fixed Stripe Price ID, checkout resolves the slider value against a matching pre-configured Stripe Product at confirmation time, so "$15" and "$32" are both first-class subscriptions rather than one plan with a custom amount bolted on.
We didn't want "enter your card" to be the default just because it's the easiest thing to build. A large share of sign-ups happen on a phone, often mid-conversation about an actual dinner someone's about to walk into — a bad moment to ask for a 16-digit number. Checkout detects Apple Pay and Google Pay support client-side via Stripe's Payment Request API and, when available, surfaces it as the primary one-tap option, backed by a live Apple Pay merchant-domain verification file — not a demo integration, an actually-registered one.
Engineering detail worth stealing: both payment paths — card and Apple Pay — terminate in the exact same subscription-creation call. Apple Pay isn't a parallel, special-cased flow bolted onto the side; it's just a different way of arriving at the same Stripe payment method, which kept the server-side surface small and easy to reason about.


| Trigger | Timing | Who Gets It |
|---|---|---|
| Dinner reminder | 48h before | Host, co-hosts & confirmed guests |
| "Invite your guests" nudge | 4h after the dinner | Host & co-hosts, only if non-member guests attended |
| Guest-invite reminder | 24h after the dinner | Host, for guests not yet invited into the club |
| Pending membership-invite reminder | 24h after invite sent | The invited guest, if still not a member |
| Host recap email | 7 days after the dinner | Host & co-hosts — full attendance & conversion breakdown |
Jobs are scheduled with deterministic IDs keyed to the dinner, so when a host reschedules, the pipeline cancels and re-creates exactly the right set of reminders instead of leaving stale ones in flight. Failed jobs retry automatically with exponential backoff, and a queue dashboard gives the team live visibility into what's running, what's stuck, and what failed.
Notifications span three channels — in-app (with a live unread badge), SMS (including a host "text blast" tool, capped at 450 characters to keep it a nudge and not a newsletter), and email (transactional plus hand-built calendar invites that work with Google, Outlook and Apple Calendar). All three are fed by the same underlying job pipeline, so a reminder is authored once and fans out to whichever channels make sense.
The back office isn't an afterthought — it's the view an operator actually needs when a dinner needs a second look, a host needs promoting, or someone needs to understand how the club is trending city over city. Filterable by city, host, date range and party size, with the same dinner data the public feed uses, just without the parts of the role model that hide things from the public.








PostHog handles product analytics — a centralized, named event registry covering signups, dinner creation, RSVP changes, co-host edits, invite flows and payments, with automatic pageview tracking and user identification.
Microsoft Clarity and Google Analytics run live in production for session replay, heatmaps and traffic analysis.
Intercom runs live in staging/pre-production only, for direct team-to-tester conversations during development — deliberately swapped out the moment a build reaches production, so the support widget never becomes noise for a real guest trying to RSVP to dinner.