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.
TL;DR
Prerequisites
Before starting your headless WooCommerce development project, you need:
- A WordPress installation with WooCommerce activated and products added
- Node.js 20+ installed locally
- Basic React and Next.js knowledge (components, hooks, data fetching)
- Familiarity with REST APIs (fetch, async/await)
- A code editor and terminal
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.
Never expose API keys to the client
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:
- WORDPRESS_URL — your WordPress site URL (e.g. https://your-store.com)
- WC_CONSUMER_KEY — the consumer key from step 1
- WC_CONSUMER_SECRET — the consumer secret from step 1
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.
100
Max products per API request
<200ms
API response time with object caching enabled
ISR
Incremental Static Regeneration for automatic page updates
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.
SEO for product pages
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.
Pros
- Client-side cart: instant interactions, no API latency, works offline
- Server-synced cart: accurate pricing, inventory checks, cross-device persistence
Cons
- Client-side cart: no server-side pricing rules, no real-time inventory
- Server-synced cart: API latency on every add/remove, more complex implementation
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.
Start simple, upgrade later
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.
- Connect your Git repository to Vercel for automatic deployments
- Add environment variables (WordPress URL, WooCommerce keys) in the Vercel dashboard
- Configure your custom domain and SSL
- Set up ISR revalidation webhooks so product changes trigger page updates
- Test the full purchase flow end-to-end before switching DNS
For WooCommerce webhooks that trigger Next.js revalidation when products or orders change, see our WooCommerce webhooks + Next.js guide.
2-4 days
Time to build a working prototype
2-6 weeks
Time to build a production-ready store from scratch
<1 day
Time to deploy with WPBundle (pre-built storefront)
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.
The 80/20 trap
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.
- Complete Next.js storefront — product listing, detail pages, and category pages
- Cart session management with server-side sync already implemented
- Stripe payment integration with checkout flow included
- Automatic SEO with JSON-LD, Open Graph, sitemaps, and meta tags
- Companion WordPress plugin extending the REST API where needed
- Edge-deployed on Vercel for sub-100ms global page loads
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.
Ready to go headless?
Join the WPBundle waitlist and get beta access completely free.
Join the Waitlist