# nextjs-woocommerce, a headless storefront on Next.js and WooCommerce

> This project is a headless eCommerce reference built on Next.js 16 and React 19, talking to WordPress and WooCommerce over GraphQL with Algolia for search and Zustand for cart state. It is a well-instrumented starter with Lighthouse, Playwright, accessibility and OWASP checks in CI, and it is licensed AGPL-3.0.

**w3bdesign/nextjs-woocommerce** — 🔥 Next.js (React) headless eCommerce site with Typescript, WordPress (WooCommerce) backend and Algolia search

- Repository: https://github.com/w3bdesign/nextjs-woocommerce
- Website: https://next-woocommerce.dfweb.no
- Stars: 610 · Forks: 156
- Language: TypeScript
- License: AGPL-3.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/w3bdesign-nextjs-woocommerce

## A storefront that never renders WordPress

The project is a headless eCommerce site: Next.js with React and TypeScript on the front, WordPress with WooCommerce behind it, and Algolia for search. The README calls it a Next.js ecommerce site with WooCommerce backend, and there is a live instance at next-woocommerce.dfweb.no.

The architecture follows from WordPress doing what WordPress is good at and Next.js doing the rest. WooCommerce holds the products, the categories, the stock and the orders, and it exposes all of that through a GraphQL API. The Next.js application never serves a WordPress page; it queries the API and renders its own front end. The topics list names the pieces: `woocommerce`, `wp-graphql`, `apollo`, `graphql`, `algolia`, `zustand` and `react-hook-form`.

Three WordPress plugins are required and one is optional, and the documentation is precise about which is which. `woocommerce` is the eCommerce package itself, `wp-graphql` exposes GraphQL for WordPress, and `wp-graphql-woocommerce` adds WooCommerce functionality to a WPGraphQL schema. The fourth, `wp-algolia-woo-indexer`, is described as a WordPress plugin coded by the author that sends WooCommerce products to Algolia, and it is stated plainly that it is required for search to work. The optional one, `headless-wordpress`, disables the WordPress frontend so only the backend is reachable, which is the piece that stops visitors landing on a half-styled WordPress theme.

That last plugin is worth a moment. A headless setup that leaves the WordPress theme live is a common half-finished state, and here it is handled by a plugin rather than left to the operator.

The audience is a developer building a WooCommerce storefront who wants the front end in React, and the second audience is a team looking for a working reference for how the pieces fit. The licence is AGPL-3.0, and the last push to the repository was on 2026-10-20.

## Four plugins, a pinned version matrix, and an env file

The installation is a numbered sequence, and the version matrix is the part that saves you time.

The current release has been tested and is confirmed working with WordPress version 7.1.3, WooCommerce version 11.2.1, WP GraphQL version 2.24.0, WooGraphQL version 1.0.3 and WPGraphQL CORS version 2.1. That last one is easy to overlook and matters, because a GraphQL API on a different origin from the front end is exactly the case that needs CORS configured, and the README lists it among the required plugins rather than leaving it to the reader.

For debugging, the documentation suggests installing the Apollo Client developer tools for either Firefox or Chrome, which is the right tool given that Apollo Client is the GraphQL client in use.

The remaining steps are the ordinary ones: make sure WooCommerce already has some products, clone or fork the repository, copy `.env.example` to `.env` and set the variables, and point the hosting platform at them. The documentation links the Vercel environment variables documentation, which is the reference for a project whose front end is expected to run on Vercel.

The environment file is short and tells you what the app talks to.

```bash
NEXT_PUBLIC_GRAPHQL_URL="https://wordpress.url.com/graphql"
NEXT_PUBLIC_ALGOLIA_INDEX_NAME= "algolia"
NEXT_PUBLIC_PLACEHOLDER_SMALL_IMAGE_URL="https://res.cloudinary.com/placeholder-337_utsb7h.jpg"
NEXT_PUBLIC_PLACEHOLDER_LARGE_IMAGE_URL="https://via.placeholder.com/600"
NEXT_PUBLIC_ALGOLIA_APP_ID = "changeme"
NEXT_PUBLIC_ALGOLIA_PUBLIC_API_KEY = "changeme"
NODE_ENV="development"
NEXT_PUBLIC_AUTH_TOKEN_SS_KEY="auth-token"
NEXT_PUBLIC_REFRESH_TOKEN_LS_KEY="refresh-token"
NEXT_PUBLIC_SESSION_TOKEN_LS_KEY="session-token"
NEXT_PUBLIC_AUTH_KEY_TIMEOUT="300000"
```

Two things to notice in that list. The GraphQL URL and the Algolia credentials are prefixed with `NEXT_PUBLIC_`, which means they are compiled into the client bundle and are visible to anyone who loads the page. The Algolia public search key is designed to be public, but the GraphQL endpoint being public is a fact about the deployment you have to accept, and the WooGraphQL schema is what it exposes. The token key names are also public prefix, so they are local storage key names rather than secrets.

Then the run and test sequence. Start the server with `pnpm run dev`, enable the COD (Cash On Demand) payment method in WooCommerce, add a product to the cart, proceed to checkout, fill in the details and place the order. That is a real end-to-end test, and it is the fastest way to find out whether your WordPress and the front end agree.

## Zustand for the cart, Apollo for the catalogue

The state management split is worth understanding because it is a deliberate two-store arrangement rather than one global store.

Apollo Client with GraphQL handles the catalogue: products, categories, listings and filters are fetched and cached through the GraphQL layer. Zustand handles the global client state, and the feature list is specific about what it is for: cart handling and checkout with WooCommerce using Zustand for state management, with persistent cart state and localStorage sync, efficient updates through selective subscriptions, type-safe cart operations, and the Cash On Delivery payment method.

The selective subscription point is the interesting one. A cart that lives in a global store and re-renders every subscriber on every change is the classic Next.js performance bug, and subscribing only the components that need a given slice is how you avoid it. That also means the cart survives a page navigation, which is what the localStorage sync gives you, so a user who browses, opens a product page and comes back keeps their cart.

The rest of the front end is ordinary but current. React Hook Form handles the checkout form and there is native HTML5 form validation on top of it, which is a sensible pairing since the browser does the first pass and the library handles the rest. Animations come from three libraries at once, Framer Motion, styled-components and Animate.css, and the loading spinner is built with styled-components, while the page load progress indicator during navigation uses Nprogress. Styling is Tailwind 3.

The catalogue side lists what the WooCommerce API returns: name, price and display image for products, with support for both simple products and variable products. Variable products are the interesting case, because they need per-variation data, and getting that right against a GraphQL schema is where most headless WooCommerce projects lose time.

Filtering is the other area the feature list spends space on: dynamic colour filtering using Tailwind's colour system with a mobile-optimised filter layout and accessible form controls with ARIA labels, a price range slider, size and colour filters, product type categorisation, and sorting options for popularity, price and newest.

## The CI setup is the part most starters skip

The badge row at the top of the README is unusual for a starter project, and it is the strongest argument for using it as a base rather than writing your own.

There is a Lighthouse CI workflow, a Playwright tests workflow, an OWASP Security workflow, an a11y workflow, plus a Codacy grade badge and a SonarCloud quality gate status. The feature list describes the Lighthouse setup as automated Lighthouse performance monitoring, with continuous performance, accessibility and best practices checks, automated reports on every pull request, and performance metrics tracking for performance score, accessibility compliance, best practices adherence, SEO optimization and Progressive Web App readiness.

The package scripts show the same thing from the developer side.

```bash
    "lhci": "lhci autorun",
    "lhci:perf": "lhci autorun --collect.settings.preset=perf",
    "lhci:desktop": "lhci autorun --collect.settings.preset=desktop",
    "playwright": "pnpm exec playwright test",
    "playwright:ui": "pnpm exec playwright test --ui",
    "playwright:codegen": "pnpm exec playwright codegen",
```

There is a `lighthouserc.json` in the repository root, so the Lighthouse configuration is committed rather than living in a CI settings file, and the Playwright config is `playwright.config.ts`.

There is also a `doctor` script, which runs `react-doctor` in verbose and score modes, a tool for analysing React code for problems. That is a newer addition and a good one to have in a reference codebase.

For a headless storefront, the accessibility and Lighthouse checks matter more than they would in an ordinary web project. A WooCommerce back end gives you a theme that is not yours and a set of product data you did not author, and the front end has to be accessible on its own terms. A project that runs an a11y check and a Lighthouse gate on every pull request is a project that has had that conversation already.

The Playwright suite is the practical part for a fork, because the end-to-end paths of a shop, browse, add to cart, checkout, are exactly what you want covered before you change anything.

## A design system with tokens, and a design that says what it is for

The project ships a custom design system built with Tailwind CSS design tokens, defined in `tailwind.config.js` and in `src/styles/globals.css`. The palette is documented in a table with a hex value and a usage note for each token.

The description is more informative than a typical colour table. The palette uses a muted slate-blue primary with warm neutral surfaces, chosen to feel calm, Nordic, and appropriate for a home goods store. The tokens run from `primary` at `#3B6B8A` for buttons, links, focus rings and active states, through `primary-light` and `primary-dark` for hover and mobile navigation, to an `accent` teal, and then the surfaces, borders and a text scale running from a warm near-black `text` down through `text-muted` and `text-light`.

The point of the token system is that the design decisions are named and in one file rather than spread across components as literal hex values. When you fork this for a different store, you edit the tokens rather than hunting for colours, and the semantics survive: `surface-alt` is documented as the image placeholder and alternating surface colour, and `border` as all borders and dividers.

Two details in the feature list fit the design story. There is a placeholder for products without images, and the placeholder image URLs are configurable through the environment variables in `.env.example`, with separate small and large variants so the image element can pick the right size without downloading the full placeholder. And the accessibility claim is stated carefully, that the project meets WCAG accessibility standards where possible, which is the honest way to put it given the a11y workflow is checking the front end and not the WordPress theme behind it.

The design system is also why the styling stack is mixed. Tailwind 3 handles layout and utility work, styled-components handles the component-level pieces like the loading spinner, and Framer Motion and Animate.css handle motion. That is more moving parts than a single system, and it is a cost, but it is the cost of a codebase that grew rather than one that was designed in one sitting.

## What the AGPL means here, and where the project stops

Two things are worth stating plainly before anyone forks this.

The first is the licence. The package manifest declares AGPL-3.0, and the licence file is at the top of the repository. The AGPL is the strongest of the common copyleft licences: it requires that a modified version distributed to users, including over a network, be offered under the same terms. For a store front end that is the whole application, not a library, that is a serious constraint on a closed-source commercial project. Read the licence before you build on this.

The second is the boundary of the project. It is a front end. The WooCommerce side, the WordPress install, the plugin set, the Algolia indexer and the payment configuration all live outside this repository. The installation steps assume you have a WordPress instance you can install plugins into and configure, and the checkout test assumes a working WooCommerce with a payment method enabled. Nothing here deploys WordPress for you.

The Algolia dependency is the sharpest edge in that boundary. Search requires the `wp-algolia-woo-indexer` plugin to push products into an Algolia index, and the plugin is a separate repository from this one. So the search feature is only as reliable as the indexing pipeline running on your WordPress side, and if that pipeline stops, your storefront keeps working but the search box quietly returns nothing. The dependency is named in the README as required for search to work, which is honest, and the front end reads the index name from `NEXT_PUBLIC_ALGOLIA_INDEX_NAME`.

A third limitation is the version matrix. The tested combination is a specific set of WordPress, WooCommerce and GraphQL plugin versions, and the headless WordPress ecosystem moves quickly. When WooCommerce changes its schema, the GraphQL plugin layer changes with it, and this front end has to be updated to match. That is the maintenance cost of a headless setup in general, and this project makes it visible rather than hiding it.

The `TODO.md` file, the `TODO/` directory, the `plans/` directory and a `SUGGESTIONS.md` linked from the table of contents all suggest the project is still in progress, and the release history backs that up with 1.2.5 in May 2026 after 1.2.4 in April 2025.

## Conclusion

nextjs-woocommerce suits a team or a developer who wants a complete, current headless WooCommerce storefront to fork rather than build from a blank Next.js project, and who will accept the AGPL-3.0 terms. It does not suit a closed-source commercial product without a licence review, since the copyleft attaches to the whole application, and it does not suit a team that does not want to run a WordPress instance at all. Verify first that the WooCommerce and WordPress versions you run match the ones the project was tested against, that your Algolia indexer is actually pushing products before you rely on search, and that the checkout flow works in your region before you take real orders through it.

## FAQ

### What does the nextjs-woocommerce project actually contain?

It is a headless eCommerce front end: Next.js 16.1.6 with React 19.2.4 and TypeScript, talking to WooCommerce through WPGraphQL, using Apollo Client for the catalogue, Zustand for cart and checkout state, and Algolia for search, with Playwright tests and Lighthouse, accessibility and OWASP checks in CI.

### Which WordPress plugins do I need to run nextjs-woocommerce?

The required plugins are woocommerce, wp-graphql, wp-graphql-woocommerce and wp-algolia-woo-indexer, the last of which sends products to Algolia and is required for search to work. The optional one, headless-wordpress, disables the WordPress frontend so only the backend is reachable.

### How do I run nextjs-woocommerce locally?

Copy .env.example to .env and set the variables, then start the server with pnpm run dev. The project uses pnpm at version 12.14.0 as its package manager, and the dev script runs next dev with Turbopack.

### Which WordPress and WooCommerce versions was this tested against?

The current release is confirmed working with WordPress 7.1.3, WooCommerce 11.2.1, WP GraphQL 2.24.0, WooGraphQL 1.0.3 and WPGraphQL CORS 2.1.

### Can I use nextjs-woocommerce for a closed-source commercial store?

The package manifest declares AGPL-3.0, which requires that a modified version distributed to users, including over a network, be offered under the same terms. That is a different situation from a permissive library licence, so read the LICENSE file and take advice before shipping a closed-source store on it.

## Sources

- [License: AGPL-3.0](https://github.com/w3bdesign/nextjs-woocommerce/blob/master/LICENSE)
- [Project website](https://next-woocommerce.dfweb.no)
- [README](https://github.com/w3bdesign/nextjs-woocommerce/blob/master/README.md)
- [Releases](https://github.com/w3bdesign/nextjs-woocommerce/releases)
- [w3bdesign/nextjs-woocommerce on GitHub](https://github.com/w3bdesign/nextjs-woocommerce)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/w3bdesign-nextjs-woocommerce
