Live demo of the Whirlwind template, as shippedStripe test mode: card 4242 4242 4242 4242, any future date, any CVCGet Whirlwind →

Payments Overview

Email-first checkout: pay on Stripe, claim access by magic link.

What ships

- Stripe Checkout for one-time payments and subscriptions - Email-first flow: pay first, claim access by magic link, no account needed to buy - A webhook that records purchases, syncs subscriptions and processes refunds - Customer portal for managing subscriptions and invoices - Duplicate detection: a session is recorded once, however many times Stripe retries

Flow

1. The buyer picks a plan; /api/stripe/create-checkout creates a Checkout session for an allowed price ID 2. Stripe hosts the payment 3. checkout.session.completed hits /api/webhook/stripe, which writes a pending_purchases row and emails a magic link 4. The buyer signs in through that link; claim_pending_purchases marks the row claimed and sets has_access on their users row 5. Subscription events keep public.subscriptions in sync; charge.refunded clears access

Test it

Use Stripe test keys and the Stripe CLI to forward webhooks locally. The Playwright flow tests exercise checkout validation and claiming; npm run doctor confirms the key mode and that the price IDs resolve.
stripe listen --forward-to localhost:3000/api/webhook/stripe