Developer Guide
Stripe Live Demo Documentation
Learn how this demo combines Next.js, Supabase, and Stripe to power one-time payments and subscriptions safely in both test and live environments.
Key Technologies
- Framework
- Next.js 15 App Router + TypeScript
- Authentication
- Supabase email/password auth
- Payments
- Stripe Checkout Sessions, Products, Prices, Subscriptions
- Styling
- Tailwind CSS
Demo Goals
- Show safe plan selection and price resolution on the server.
- Demonstrate Supabase-to-Stripe customer linking.
- Preserve app/store separation with Stripe metadata.
- Illustrate how to flip between test and live modes.
Architecture Overview
Request Flow
- Supabase guards every API route. If the session is invalid we return
401 Unauthorized. - The browser sends only a
tierslug (e.g.,"basic","donate"). Prices are never client-controlled. - The server resolves that slug to an environment-specific Stripe Price ID, creates or reuses the customer, and launches a Checkout Session.
- Metadata (
app,store,tier) is attached to customers, prices, and subscriptions so multiple apps can share one Stripe account.
Primary Pages
- /payment: one-time Checkout using the
donateprice. - /subscribe: loads live plan details directly from Stripe and launches subscription Checkout.
- /subscriptions: lists subscriptions for the logged-in user and allows safe cancellation.
- /dashboard: protected view with user info and high-level stats (per test/live mode).
Setup Guide
1. Environment Variables
Create .env.local with your Supabase keys, Stripe secret keys, and both sets of price IDs:
NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_ANON_KEY= SUPABASE_SERVICE_ROLE_KEY= NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= STRIPE_SECRET_KEY= NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY_LIVE= STRIPE_SECRET_KEY_LIVE= STRIPE_TEST_PRICE_DONATE= STRIPE_TEST_PRICE_SUB_BASIC= STRIPE_TEST_PRICE_SUB_STANDARD= STRIPE_TEST_PRICE_SUB_PREMIUM= STRIPE_LIVE_PRICE_DONATE= STRIPE_LIVE_PRICE_SUB_BASIC= STRIPE_LIVE_PRICE_SUB_STANDARD= STRIPE_LIVE_PRICE_SUB_PREMIUM=
2. Stripe Products & Prices
- Create one product per demo app (e.g., “Stripe Demo App Product”).
- Add recurring prices (basic, standard, premium) and a one-time price (donate) in both test and live mode.
- Assign lookup keys such as
stripe-live:subscription:basicand metadata like{ app: 'stripe-live', store: 'default', tier: 'basic', environment: 'test' }. - Duplicate the setup for live mode with identical metadata but environment=live.
3. Supabase configuration
- Enable email/password sign-in and configure redirect URLs inside Supabase Auth settings.
- Set your production URL in Supabase so auth callbacks succeed in production.
- Optional: configure SMTP (e.g., Resend) if you want to test email confirmations.
Security Highlights
- Server-owned pricing: Checkout sessions accept only server-resolved price IDs. Client payloads can’t alter amounts.
- Session-bound subscriptions: Cancellation and listing routes verify that the Stripe customer belongs to the Supabase user.
- Metadata filtering: Customers, prices, and subscriptions are tagged, letting one Stripe account serve multiple apps safely.
- API version pinning: Stripe SDK initialises with a supported API version to avoid surprises.
Running the Demo
npm install npm run dev
- Visit
/paymentto test one-time charges in test or live mode. - Visit
/subscribeto explore subscription tiers fetched directly from Stripe. - Manage active plans on
/subscriptionsand track stats on/dashboard.
Troubleshooting
- Unexpected checkout total? The Stripe customer may have an outstanding balance. Clear it from the Stripe dashboard or create a new test user.
- “Invalid price tier” error? Ensure the plan slug matches the configured price IDs and environment variables.
- Subscriptions list empty? Confirm the Stripe customer’s metadata matches
app=stripe-liveand the user’s email.