Headless WooCommerce Tutorial: Build a Next.js Storefront
This headless WooCommerce tutorial walks you through building a decoupled storefront step by step. No theory-heavy introductions — we assume you know what headless means and want to start building. By the end, you will have a Next.js frontend connected to WooCommerce's REST API, rendering products, handling cart state, and ready for checkout integration.
Prerequisites
Before starting your headless WooCommerce development project, you need:
Your WooCommerce store can be local (LocalWP, MAMP) or hosted. For development, local is faster. For production, you will need a hosted WordPress instance — see our best WooCommerce hosting guide for options.
Step 1: Configure WooCommerce API access
WooCommerce includes a REST API out of the box. You need to generate API credentials and configure your WordPress installation for headless use.
Generate API keys
In your WordPress admin, go to WooCommerce → Settings → Advanced → REST API. Click “Add key” and create a key with Read/Write permissions. Save the Consumer Key and Consumer Secret — you will need both for API authentication.
Enable pretty permalinks
The WooCommerce REST API requires pretty permalinks. Go to Settings →
Permalinks and select any option other than “Plain.” Post
name (/%postname%/) is the most common choice.
Handle CORS
If your Next.js frontend and WordPress backend run on different
domains (they will in production), you need to allow cross-origin
requests. Add CORS headers to your WordPress installation via a plugin
or a small snippet in functions.php. Alternatively, proxy
API requests through Next.js API routes to avoid CORS entirely — this
is the approach WPBundle uses and it is more secure because your
WooCommerce credentials never reach the browser.
Step 2: Scaffold your Next.js project
Create a new Next.js project with the App Router. The App Router is the recommended architecture for new Next.js projects and provides server components, streaming, and better data fetching patterns.
Run npx create-next-app@latest my-store and select
TypeScript, Tailwind CSS, and the App Router when prompted. Add your
WooCommerce credentials as environment variables in
.env.local:
Create a WooCommerce API utility
Build a reusable fetch wrapper that handles authentication and error
handling. This utility should construct the full API URL, append
authentication parameters, and return typed JSON responses. The
WooCommerce REST API base path is
/wp-json/wc/v3/. For a deeper dive into the API
structure, see our
WooCommerce REST API + Next.js
guide.
Step 3: Build the product listing page
Your shop page fetches products from the WooCommerce API and renders them as a grid. Using a React Server Component, the data fetching happens on the server — no client-side loading spinners needed.
Fetching products
Call /wp-json/wc/v3/products with parameters for
pagination, category filtering, and ordering. The API returns product
objects with name, price, images, categories, and more. Key parameters
to use: per_page (default 10, max 100),
page for pagination, category for filtering,
and orderby for sorting.
Rendering the grid
Map over the products array and render a card component for each. Use
Next.js Image component for product images — it handles lazy loading,
responsive sizing, and WebP conversion automatically. Link each card
to /products/[slug] for the detail page.
Pagination
The WooCommerce API returns total product count and page count in
response headers (X-WP-Total and
X-WP-TotalPages). Use these to build pagination controls.
For SEO, use URL-based pagination (/shop?page=2) rather
than client-side state so each page is indexable.
Step 4: Build the product detail page
Each product gets its own page at /products/[slug]. This
page fetches a single product by slug and renders the full product
experience: images, title, price, description, variations (if
variable), and an add-to-cart button.
Static generation with ISR
Use generateStaticParams to pre-build product pages at
deploy time. Fetch all product slugs and return them as params. Enable
ISR with a revalidation period (e.g. 60 seconds) so pages update
automatically when product data changes in WooCommerce — without
rebuilding the entire site.
Variable products
WooCommerce variable products (sizes, colours) require fetching
variations via /products/{id}/variations. Each
variation has its own price, stock status, and image. Build a client
component that lets customers select attributes and updates the
displayed price and image accordingly. This is one of the more
complex parts of a headless WooCommerce build — see our
variable products
guide for performance considerations.
Product images
WooCommerce returns image URLs from your WordPress media library.
Configure Next.js next.config.js to allow images from
your WordPress domain. Use the Image component with
sizes and priority props for the main
product image (above the fold) and lazy loading for gallery images.
Step 5: Implement cart state
The cart is the hardest part of any headless WooCommerce build. In traditional WooCommerce, cart state lives in PHP sessions on the server. In a headless setup, you need a different approach.
Client-side cart (simplest)
Store cart state in React context or Zustand, persisted to localStorage. Products are added and removed entirely on the client. This is fast and simple but means the cart exists only in the browser — it does not sync with WooCommerce until checkout.
Server-synced cart (recommended for production)
Use WooCommerce's Store API (/wp-json/wc/store/v1/cart)
or a plugin like CoCart to maintain cart state on the server. This
ensures cart data persists across devices, respects server-side pricing
rules (coupons, dynamic pricing), and keeps inventory accurate. The
trade-off is API latency on every cart operation.
For a deep dive into cart session management, see our headless WooCommerce cart sessions guide.
Step 6: Connect checkout
Checkout is where headless WooCommerce gets genuinely complex. You have three main options, each with different trade-offs.
Option 1: Redirect to WooCommerce checkout
The simplest approach. When the customer clicks “Checkout,” redirect them to your WordPress site's native checkout page. This uses WooCommerce's built-in checkout with all its payment gateways, tax calculation, and shipping logic. The downside: customers leave your fast headless frontend for a slower PHP-rendered page.
Option 2: Stripe Checkout (hosted)
Create a Stripe Checkout session from your Next.js API route, passing the cart items and prices. Stripe handles the entire checkout UI, payment collection, and PCI compliance on their hosted page. After payment, create the WooCommerce order via API. This is the fastest path to a working headless checkout. See our Stripe checkout integration guide.
Option 3: Custom checkout with Stripe Elements
Build a fully custom checkout form with address fields, shipping options, and Stripe Elements for payment. This gives you complete design control but requires implementing address validation, tax calculation, shipping rate fetching, and order creation yourself. This is the most work but produces the best customer experience. For the full architectural breakdown, see our headless checkout guide.
Step 7: Deploy and go live
Deploy your Next.js frontend to Vercel, Netlify, or Cloudflare Pages. Vercel is the most seamless option for Next.js — zero configuration, automatic preview deployments, and edge caching built in.
For WooCommerce webhooks that trigger Next.js revalidation when products or orders change, see our WooCommerce webhooks + Next.js guide.
Common pitfalls
Underestimating the cart and checkout
Product listing and detail pages are the easy part — they are mostly read-only data display. The cart (state management, session persistence, pricing rules) and checkout (payment, tax, shipping, order creation) are where 70% of the development effort goes. Plan your timeline accordingly.
Ignoring WooCommerce API limitations
The WooCommerce REST API does not expose everything. Some data requires custom endpoints or the WPGraphQL plugin. Common gaps: advanced product filtering, real-time inventory, and complex shipping calculations. Check the API documentation for your specific requirements before committing to an architecture. For a comparison of API options, see our REST API vs WPGraphQL guide.
Skipping SEO implementation
A headless frontend that does not implement meta tags, structured data, canonical URLs, and sitemaps will lose search rankings. This is not optional — it must be built from the start, not bolted on later.
How WPBundle helps
This tutorial covers the fundamentals of headless WooCommerce development, but building a production-ready store from scratch takes weeks of work on cart sessions, checkout flows, payment integration, SEO, and API gaps. WPBundle provides all of this out of the box.
If you want to learn headless WooCommerce development, follow this tutorial. If you want a production store shipping this week, start with WPBundle and customise from there. Either way, your WooCommerce backend stays exactly where it is — only the frontend changes.
Keep reading
Related guides you might find useful
Best AI Product Description Plugins for WooCommerce (2026)
A hands-on comparison of WriteText.ai, AI Product Tools, and other AI description generators for WooCommerce — features, pricing, and which one actually saves time.
Read guideTutorialsHow to Generate Bulk Product Descriptions in WooCommerce
Stop writing product descriptions one at a time. Here's how to generate hundreds of WooCommerce descriptions using AI — the tools, the process, and the pitfalls.
Read guideTutorialsAI SEO Product Descriptions for WooCommerce: Do They Actually Rank?
AI-generated product descriptions are fast — but do search engines reward them? The data on AI content SEO for WooCommerce stores.
Read guideLevel up your WooCommerce store
Join the WPBundle waitlist and get beta access to our plugin suite completely free.
Join the Waitlist