← Back

Membership Platform

A subscription membership platform for a coaching business — curriculum delivery, live coaching, and Stripe billing.

Role
AI Engineer
Year
2026
Status
In production

A membership platform for a coaching business. It delivers a structured curriculum, books live coaching sessions, and takes subscription payments. Members work through modules at their own pace; the business runs the whole thing — content, events, pricing, support — from an admin surface inside the same app.

The interesting problems were never the CRUD. They were the places where money, access and identity meet: what happens when somebody pays and then closes the tab, how an owner can run the business without being able to lock out the developer maintaining it, and how to make failures loud enough that nobody silently loses the access they paid for.

Architecture

Next.js App Router on Vercel, Supabase for Postgres, auth and storage, Stripe for billing. JWT validation happens at the edge, in middleware, before a request reaches a page. Above that sit three guards that compose: one requires a session, one requires an active subscription, one additionally requires the welcome series to be finished. Row-level security in Postgres enforces the same rules a second time, so a missed guard is a bug rather than a breach.

Access has three tiers — member, owner and developer — and the only power reserved to developer is granting and revoking access. That single boundary means the person running the business cannot accidentally lock out the person maintaining it, and a compromised owner account cannot mint new admins. The tier and the older is_admin boolean are kept honest by a CHECK constraint: a write that sets one without the other is rejected by the database, rather than trusted to be caught in review.

Checkout runs two flows. A cold one for visitors who pay before they have an account, and a warm one for members who already do. The cold flow creates the account after payment, which leaves an obvious hole — the buyer who closes the tab. The webhook is the safety net: it provisions the user passwordless and sends a recovery email. It also answers 500 on internal failure so Stripe retries. The previous behaviour returned 200 to everything, which meant a transient database error could quietly cost a paying customer their access and leave nothing behind to find it by.

Membership platform architecture Four layers. Member and owner browsers reach edge middleware that validates the JWT before a page is served. A guard chain composing auth, subscription and curriculum checks sits in front of the pages, and row-level security repeats those rules inside Postgres. Route handlers call Stripe for checkout; Stripe posts subscription events back to a webhook handler that provisions buyers who closed the tab and answers 500 on failure so delivery is retried. An MCP server calls the same route handlers as the owner using a personal access token. Server and browser errors go to Sentry. Clients Edge Application Data & services Member browser Curriculum, coaching, billing React 19 client Owner browser Admin surface Content, events, pricing Claude desktop MCP client On the owner's machine Edge middleware JWT validation · public-path allowlist Runs before the page is reached MCP server Own package, outside the build Personal token · acts as the user Guard chain Auth → Subscription → Curriculum RLS repeats it in Postgres Pages Server components Static curriculum data Progress read per member Route handlers /api/* — admin, billing, content The same routes MCP calls Webhook handler /api/stripe/webhook Provisions the closed-tab buyer 500 on failure → Stripe retries Supabase Postgres + row-level security Auth · Storage SQL migrations Stripe Embedded Checkout · Customer Portal Subscription + invoice events Trials · dunning Sentry Server error hook Browser events tunnelled same-origin 1 2 3 4 5
1 Member request 2 Checkout 3 Stripe events · asynchronous 4 Admin over MCP 5 Errors · asynchronous

Platforms used

Application

  • Next.js 16 · App Router
  • React 19
  • TypeScript (strict)
  • Tailwind CSS v4
  • Turbopack

Data & auth

  • Supabase Postgres
  • Supabase Auth
  • Row-level security
  • SQL migrations

Payments

  • Stripe Embedded Checkout
  • Customer Portal
  • Webhooks
  • Trials & dunning

Operations

  • Vercel
  • Sentry
  • Model Context Protocol

Features

Screens

Member home — progress, next lesson, what is coming up
Member home — progress, next lesson, what is coming up
Curriculum — modules, lesson types, per-member progress
Curriculum — modules, lesson types, per-member progress
Workshops — upcoming live calls and the replay archive
Workshops — upcoming live calls and the replay archive
← Back