Stripe Subscriptions with Next.js: Complete Integration Guide 2026
Stripe subscriptions are the backbone of SaaS billing. This guide covers the complete integration with Next.js App Router, including product setup, checkout, webhooks, and the customer portal.
Setting Up Products in Stripe
Create products and prices programmatically for consistency:
import Stripe from 'stripe'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
async function createProductWithPrices() {
const product = await stripe.products.create({ name: 'Pro Plan' })
const monthly = await stripe.prices.create({
product: product.id, unit_amount: 2900, currency: 'usd',
recurring: { interval: 'month' },
})
const yearly = await stripe.prices.create({
product: product.id, unit_amount: 29000, currency: 'usd',
recurring: { interval: 'year' },
})
return { product, monthly, yearly }
}Checkout Flow
Use Stripe Checkout for a hosted payment page:
// app/api/checkout/route.ts
import Stripe from 'stripe'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
export async function POST(req: Request) {
const { priceId, userId } = await req.json()
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
payment_method_types: ['card'],
line_items: [{ price: priceId, quantity: 1 }],
success_url: `${process.env.NEXT_PUBLIC_URL}/dashboard?upgraded=true`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
metadata: { userId },
subscription_data: { trial_period_days: 14 },
})
return Response.json({ sessionId: session.id })
}Webhook Handling
Handle essential events to keep your database in sync:
export async function POST(req: Request) {
const body = await req.text()
const sig = (headers()).get('stripe-signature')!
const event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!)
switch (event.type) {
case 'checkout.session.completed': {
const session = event.data.object as Stripe.Checkout.Session
await prisma.user.update({
where: { id: session.metadata!.userId },
data: { stripeCustomerId: session.customer as string, plan: 'pro' },
})
break
}
case 'customer.subscription.deleted': {
const sub = event.data.object as Stripe.Subscription
await prisma.user.updateMany({
where: { stripeSubscriptionId: sub.id },
data: { plan: 'free', subscriptionStatus: 'cancelled' },
})
break
}
case 'invoice.payment_failed': {
const invoice = event.data.object as Stripe.Invoice
await sendPaymentFailedEmail(invoice.customer_email!)
break
}
}
return Response.json({ received: true })
}Customer Portal
Let customers manage subscriptions through the Stripe Customer Portal with one API call.
Usage-Based Billing
For metered pricing, report usage to Stripe with subscriptionItems.createUsageRecord.
The Bottom Line
Stripe integration follows a clear pattern: products, checkout, webhooks, portal. The Ecommerce Starter from BreafIO includes pre-built Stripe integration. The SaaS Starter Kit provides complete subscription management. The Subscription Hub offers focused billing. The API Boilerplate is great for billing services, and the Landing Page Bundle helps market pricing tiers.
Related Template
Try this production-ready starter kit to build your project faster.
Shop All Products
Wireless Headphones
Leather Backpack
Smart Watch
Sunglasses
E-Commerce Starter
Build your online store the smart way
Ready to Build?
Get started with our production-ready starter kits and ship your project faster.
Browse Starter Kits