Full Stack 51:102025-08-28
Stripe Subscriptions in Next.js: The Complete Setup
How to implement Stripe recurring billing — checkout sessions, webhooks, customer portal, and subscription status management — in a Next.js App Router app.
Watch on YouTube
Click to open in YouTube
Video Notes & Code
Key takeaways, code snippets, and resources from this video.
Checkout Session
typescript
// 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_SITE_URL}/dashboard?success=1`,
cancel_url: `${process.env.NEXT_PUBLIC_SITE_URL}/pricing`,
metadata: { userId },
})
return Response.json({ url: session.url })
}Webhook Handler
typescript
// app/api/webhooks/stripe/route.ts
export async function POST(req: Request) {
const sig = req.headers.get('stripe-signature')!
const body = await req.text()
const event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!)
if (event.type === 'customer.subscription.updated') {
const sub = event.data.object as Stripe.Subscription
await db.update(users).set({
subscriptionStatus: sub.status,
planId: sub.items.data[0].price.id,
}).where(eq(users.stripeCustomerId, sub.customer as string))
}
return new Response(null, { status: 200 })
}Found this useful?
Subscribe for weekly content on AI engineering, SaaS building, and full stack development.