Stripe Starter — Subscriptions & Payments for Next.js (Supabase + Drizzle)
Stripe subscriptions & one-time payments for Next.js + Supabase: Checkout, webhooks with replay protection, customer portal, access gating. Runtime-verified.

Type
Tech stack
Documentation
Full
Setup, architecture, and how the pieces fit together.
Maintenance
None
Sold as-is. No further updates from the Builder.
Description
Billing, already wired. Checkout, webhooks, the customer portal, and the part most tutorials skip — actually reading subscription state to gate access.
Next.js 15 · React 19 · TypeScript · Supabase · Drizzle · Stripe · Tailwind v4
Why this exists
Taking a payment is the easy half. Most Stripe guides stop at "redirect to Checkout" and leave you to discover the rest in production. This starter handles what they skip:
- Every checkout creating a new Stripe customer, splitting one person's billing history → one customer per user, for life — safe even under concurrent checkouts (idempotency key + database-arbitrated claim)
- Stripe retrying webhooks and double-granting entitlements → every event id recorded, duplicates skipped, verified against Stripe's own redelivery
- Parsing the body breaking signature verification → raw body verified first, always
- "Is this user subscribed?" →
getSubscription()reads a local mirror in one indexed query;requireActiveSubscription()andhasPurchased()for gating - A subscribed user picking another plan getting a second subscription billing in parallel → existing subscriptions are switched in place, prorated by Stripe
- Refunded purchases keeping access forever →
charge.refundedrevokes; partial refunds keep access - Users editing their own billing rows → RLS + column grants make billing tables read-only to users; only the webhook writes
- The displayed price drifting from what Stripe charges →
pnpm check:pricesfails on any mismatch
What you get
- Subscription checkout with optional free trials, plus one-time purchases (lifetime deals) alongside
- Stripe customer portal for cancellations, plan changes, cards and invoices
- Cancelled subscriptions keep access until period end — gating logic accounts for it
- Supabase email/password auth (Google OAuth behind a flag), signup trigger, RLS on every table
- Drizzle schema + two migrations, dark/light themes, pricing/billing/dashboard pages
AGENTS.md: an ordered setup runbook written to be handed to a coding agent — every key, every dashboard step, a verification checklist, and a failure-symptom reference table
Verified, not sketched
Real payments have flowed through this exact code in Stripe test mode: card checkout, trials, cancellation-keeps-access, plan switching (one subscription before and after, prorated), declined cards granting nothing, refund revocation, replay-deduped webhooks, and 27 access-control checks including cross-user attacks and privilege escalation. 57 automated checks pass on a clean clone.
What's not included
No tax handling (enable Stripe Tax), no metered/usage billing, no multi-seat, no email sending, no admin dashboard. Fixed-price plans and one-time products only.
Services required
Supabase (free tier is enough) and Stripe (test mode is free). Google Cloud only if you want Google sign-in.
Domains
Seller
Reviews
No reviews yet.
Related reading
A breakdown of what an online store for the Egyptian market actually needs, and where starting from a finished build saves you a quarter.
