Stripe Experts
PlatformsIndustriesBlog
Book a Free Consultation
Stripe Experts

Trusted Stripe integration services for SaaS, marketplaces, and e-commerce.

Company

  • About
  • Blog
  • Contact

Services

  • All Services
  • Stripe Checkout
  • Stripe Connect
  • Stripe Billing

Industries

  • SaaS
  • Marketplace
  • Healthcare
  • Fintech

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Stripe Experts. All rights reserved.

Not affiliated with Stripe, Inc. Independent Stripe integration partner.

  1. Home
  2. Blog
  3. Stripe Tutorials
  4. How to Add Stripe to a Next.js 15 App Router Project
Stripe Tutorials

How to Add Stripe to a Next.js 15 App Router Project

Server Actions, Route Handlers, and the runtime gotcha that breaks most first attempts.

Z

Zeeshan

Founder · Published Jan 19, 2026

App Router changes the shape of a Stripe integration more than most teams expect. The old "API routes" mental model still mostly works, but two things trip up almost every first attempt: Server Actions for creating sessions, and the runtime configuration on your webhook handler.

Creating a Checkout Session

A Server Action is the cleanest way to create a Checkout Session from a form submission — no separate API route needed for the simple case.

"use server";

export async function createCheckoutSession() {
  const session = await stripe.checkout.sessions.create({
    mode: "payment",
    line_items: [{ price: "price_123", quantity: 1 }],
    success_url: `${process.env.SITE_URL}/success`,
    cancel_url: `${process.env.SITE_URL}/cancel`,
  });
  redirect(session.url!);
}

The Webhook Runtime Gotcha

Webhook signature verification needs the raw request body and Node.js APIs — it will not work on the Edge runtime. Explicitly force the Node runtime on your webhook route.

export const runtime = "nodejs";

export async function POST(req: Request) {
  const body = await req.text();
  const sig = req.headers.get("stripe-signature")!;
  const event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
  // handle event
}

Miss this and signature verification fails intermittently in production while working fine locally — a classic case of an environment difference masking the real bug.

#nextjs#checkout

Stripe insights, monthly

One email a month, no spam, unsubscribe anytime.

No spam, unsubscribe anytime.

On This Page

  • Creating a Checkout Session
  • The Webhook Runtime Gotcha

Related Services

Stripe Checkout

Fully hosted, brand-matched Stripe Checkout, live in days.

Learn more

Webhooks

Production-grade Stripe webhook handling, verified and monitored.

Learn more

API Integration

Custom Stripe API integration for your exact business logic.

Learn more

Related Reading

Stripe Tutorials

Adding Stripe Payments to a Shopify Store Beyond the Default Plugin

Shopify Payments covers standard storefronts well — here's where it stops being enough.

Apr 13, 2026Read
Stripe Tutorials

Integrating Stripe with Laravel: A Step-by-Step Guide

When to reach for Cashier, and when to go straight to the Stripe PHP SDK instead.

Apr 6, 2026Read
Stripe Tutorials

Building a Self-Serve Customer Portal with Stripe Billing

Every support ticket a customer can resolve themselves through a portal is a ticket your team never has to touch.

Mar 9, 2026Read