The Next.js SaaS Starter uses Stripe for subscription billing, payment processing, and customer management. This guide covers everything you need to configure Stripe for your application.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nextjs/saas-starter/llms.txt
Use this file to discover all available pages before exploring further.
Prerequisites
Before configuring Stripe, you’ll need:- A Stripe account (Sign up)
- Stripe CLI installed (Installation guide)
- Stripe CLI authenticated (
stripe login)
Stripe API Configuration
The Stripe client is initialized inlib/payments/stripe.ts:
lib/payments/stripe.ts
Required Environment Variables
Add these to your.env file:
Your Stripe secret API keyFormat:
sk_test_... (test mode) or sk_live_... (production)Where to find it: Stripe Dashboard → API KeysWebhook signing secret for verifying eventsFormat:
whsec_...See Webhook Configuration below for setup instructions.Your application’s base URL for redirectsDevelopment:
http://localhost:3000Production: https://yourdomain.comGetting Your API Keys
Test Mode (Development)
- Go to Stripe Dashboard
- Ensure you’re in Test mode (toggle in top right)
- Copy the “Secret key” (starts with
sk_test_) - Add to
.env:
Live Mode (Production)
- Switch to Live mode in Stripe Dashboard
- Copy the “Secret key” (starts with
sk_live_) - Update your production
.envwith the live key - Complete Stripe account verification before processing real payments
Subscription Products Setup
The starter includes a seed script that creates subscription products in Stripe.Creating Products with Seed Script
Run the database seed command:- Name: “Base”
- Price: $8.00/month
- Trial: 7 days
- Billing: Monthly recurring
- Name: “Plus”
- Price: $12.00/month
- Trial: 7 days
- Billing: Monthly recurring
Products are created in cents.
unit_amount: 800 = $8.00 USD.Seed Script Details
Fromlib/db/seed.ts:
lib/db/seed.ts
Manual Product Creation
You can also create products manually in the Stripe Dashboard:- Click “Add product”
- Enter product name and description
- Set pricing model to “Recurring”
- Configure price and billing interval
- Add trial period if desired
- Save the product
Checkout Session
The application uses Stripe Checkout for subscription sign-ups.Implementation
Fromlib/payments/stripe.ts:
Checkout Features
Accepted payment methods - currently
['card']Set to
'subscription' for recurring billingRedirect URL after successful payment:
/api/stripe/checkout?session_id={CHECKOUT_SESSION_ID}Redirect URL if user cancels:
/pricingEnables promo code input during checkout
Free trial duration - set to 14 days
Customer Portal
Stripe Customer Portal lets users manage their subscription, payment methods, and billing history.Implementation
Fromlib/payments/stripe.ts:
Portal Features
✅ Subscription updates: Change plan, quantity, or apply promo codes ✅ Subscription cancellation: Cancel at period end with feedback ✅ Payment methods: Update card information ✅ Billing history: View invoices and receipts ✅ Proration: Automatic prorated charges when upgrading/downgradingWebhook Configuration
Webhooks enable Stripe to notify your application about subscription changes.Events Handled
The webhook endpoint (app/api/stripe/webhook/route.ts) handles:
customer.subscription.updated- Subscription changes (plan upgrades, renewals, etc.)customer.subscription.deleted- Subscription cancellations
app/api/stripe/webhook/route.ts
Development Setup (Stripe CLI)
For local development, use the Stripe CLI to forward webhook events:- Install Stripe CLI: Follow the installation guide
-
Authenticate:
-
Get webhook secret:
Copy the webhook secret (
whsec_...) to your.env: -
Start webhook forwarding:
Keep the
stripe listen command running while developing. It forwards Stripe events to your local server.Production Setup
- Go to Stripe Dashboard → Webhooks
- Click “Add endpoint”
-
Enter endpoint URL:
-
Select events to listen to:
customer.subscription.updatedcustomer.subscription.deleted
-
Copy signing secret:
- After creating the endpoint, copy the “Signing secret”
- Update your production
.env:
Webhook Security
Stripe signs webhook events to prevent tampering. The verification process:- Stripe sends event with
stripe-signatureheader - Your app verifies the signature using
STRIPE_WEBHOOK_SECRET - If valid, the event is processed
- If invalid, a 400 error is returned
Subscription Management
ThehandleSubscriptionChange function updates your database when subscriptions change:
lib/payments/stripe.ts
Subscription Statuses
active: Subscription is active and paidtrialing: In free trial periodcanceled: Subscription has been cancelledunpaid: Payment failedpast_due: Payment is overdue
Testing
Test Card Numbers
Stripe provides test cards for development:Testing Webhooks Locally
-
Start your development server:
-
Start Stripe webhook forwarding:
-
Trigger test events:
- Check your application logs to verify webhook processing
Testing Subscriptions
- Create a checkout session with a test price ID
- Use test card
4242 4242 4242 4242 - Complete checkout
- Verify subscription appears in:
- Your database (
teamstable) - Stripe Dashboard → Customers
- Your database (
- Test the customer portal:
- Update payment method
- Cancel subscription
- View invoices
Retrieving Products and Prices
Helper functions to fetch Stripe data:lib/payments/stripe.ts
Production Checklist
Before going live:- Switch to live API keys (
sk_live_...) - Create live products and prices
- Configure production webhook endpoint
- Update
BASE_URLto production domain - Complete Stripe account activation
- Set up tax collection (if required)
- Configure email receipts and invoices
- Test the complete checkout flow
- Test webhook delivery in production
- Monitor Stripe logs for errors
Troubleshooting
Webhook signature verification failed
Cause:STRIPE_WEBHOOK_SECRET is incorrect or missing
Solution:
- Development: Run
stripe listen --print-secretand copy the secret - Production: Get the secret from your webhook endpoint in Stripe Dashboard
No such customer
Cause: Team doesn’t have astripeCustomerId set
Solution: Ensure the checkout session sets the customer ID correctly
Subscription not updating in database
Cause: Webhook not being received or processed Solution:- Check
stripe listenis running (development) - Verify webhook endpoint is configured (production)
- Check application logs for errors
- Verify
handleSubscriptionChangeis being called
Test mode mismatch
Cause: Using test API key with live webhook secret (or vice versa) Solution: Ensure all Stripe resources (keys, products, webhooks) are in the same modeNext Steps
Environment Variables
Review all configuration options
Database Setup
Set up PostgreSQL and migrations