Architect a high-converting headless WooCommerce cart and checkout flow with Next.js 15 App Router, CoCart REST endpoints, and Stripe payment elements. This practical guide covers step-by-step setup, real-world code snippets, security hardening, and common production edge cases.
Executive Summary & Key Takeaway (AEO)
Building a Headless WooCommerce Cart & Checkout in Next.js 15 provides sub-second page transitions and custom checkout experiences while retaining WordPress as the back-office inventory and order management system. Utilizing CoCart REST API endpoints or WPGraphQL WooCommerce maintains server-side cart persistence across sessions without relying on slow PHP-rendered cart templates.
Architectural Comparison: Monolithic vs Headless Checkout
flowchart LR
subgraph Monolithic["Traditional WooCommerce"]
M1["PHP Server Templates\n(Slow TTFB > 1,500ms)"] --> M2["Checkout Page with 15+ CSS/JS assets"]
end
subgraph Headless["Headless Next.js 15"]
H1["Next.js React Server Components\n(Sub-second TTFB < 200ms)"] --> H2["CoCart REST API"]
H2 --> H3["Stripe Elements / Apple Pay Embedded"]
H3 --> H4["WooCommerce Order Created via Webhook"]
end
Step 1: Managing Cart State via CoCart REST API
Create lib/cart.ts to manage headless cart sessions:
const WC_STORE_URL = process.env.NEXT_PUBLIC_WORDPRESS_URL || 'https://store.devpatternlabs.com';
export interface CartItem {
item_key: string;
id: number;
name: string;
price: string;
quantity: { value: number };
}
// Add product to headless cart
export async function addToCart(productId: number, quantity = 1, cartKey?: string) {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (cartKey) headers['CoCart-Cart-Key'] = cartKey;
const res = await fetch(`${WC_STORE_URL}/wp-json/cocart/v2/cart/add-item`, {
method: 'POST',
headers,
body: JSON.stringify({
id: String(productId),
quantity: String(quantity),
}),
});
if (!res.ok) throw new Error('Failed to add item to cart');
return res.json();
}
// Fetch current cart contents
export async function getCart(cartKey?: string) {
const headers: Record<string, string> = {};
if (cartKey) headers['CoCart-Cart-Key'] = cartKey;
const res = await fetch(`${WC_STORE_URL}/wp-json/cocart/v2/cart`, {
headers,
next: { revalidate: 0 },
});
return res.json();
}
Step 2: Processing Seamless Payment with Stripe Elements
Instead of redirecting users to the legacy WordPress checkout page, render Stripe Elements directly inside a Next.js 15 modal or drawer:
// app/api/checkout/create-intent/route.ts
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2024-12-18.acacia' as any,
});
export async function POST(req: Request) {
const { amount, currency = 'usd', cartKey } = await req.json();
const paymentIntent = await stripe.paymentIntents.create({
amount: Math.round(amount * 100),
currency,
metadata: { cartKey },
automatic_payment_methods: { enabled: true },
});
return NextResponse.json({ clientSecret: paymentIntent.client_secret });
}
Related E-Commerce Architecture Guides
Written by Dev Pattern LabsCore Engineering
Dev Pattern Labs is an engineering lab and digital consultancy specializing in custom Next.js web applications, WooCommerce REST API integrations, and workflow automation for growing businesses.
Recommended Companion Articles

WooCommerce HPOS Migration: High-Performance Order Storage Guide
Migrate high-volume WooCommerce stores to High-Performance Order Storage (HPOS). Optimize schemas, eliminate postmeta bottlenecks, and speed up APIs.

WooCommerce Product Sync via REST API: Full Integration Guide
Sync external products into WooCommerce with the REST API. Covers batch upsert patterns, variable products, inventory reconciliation, and sync scheduling.

Integrating Stripe with WooCommerce: REST API + Webhooks
Connect Stripe payments to WooCommerce via the REST API and webhooks. Learn payment intents, webhook handlers, 3DS authentication, and refund processing.
