Open-source project
scottyzen/woonuxt avatar
scottyzen/woonuxt

WooNuxt: a static or ISR front end for a WooCommerce store

Static e-commerce powered by WooCommerce & Nuxt

972 stars297 forksVueGPL-3.0

At a glance

What is it?
WooNuxt puts a Nuxt 4 and WPGraphQL front end in front of WordPress WooCommerce, so the catalogue can be prerendered as static pages or served with incremental static regeneration for large catalogues, while cart and checkout stay dynamic. The documentation is unusually candid about the deployment traps, from the publish directory that silently breaks the bundle to the image provider that needs a running server.
Who is it for?
Adopt WooNuxt when you run a WooCommerce store whose catalogue pages should be fast and indexable, and when you are willing to keep WordPress as the source of truth behind a GraphQL layer rather than moving the data.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Vue, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

WordPress stays behind it, and the catalogue moves to the front

WooNuxt is a modern, fast and SEO-friendly front end for WooCommerce, built on Nuxt 4 and WPGraphQL. It supports both fully static deployment and hybrid ISR rendering for large catalogues, and it is fully customizable and extensible with custom components and modules.

The architecture is decoupled but not migrated. The product data still lives in WordPress, WooCommerce still owns the order and payment side, and the new front end reads through the GraphQL API. That is a smaller and safer change than replacing the store, and it is why the project can be adopted in front of an existing catalogue rather than as part of a rebuild.

There are live deployments listed in the README, which is the most useful thing for judging the result before you install anything: a primary demo at demo.woonuxt.com, plus examples running on Vercel, on NuxtHub, and a customised store at myshop.woonuxt.com. Seeing the customised one matters, because the point of the project is that you end up with your own store rather than the demo.

The implementation language is Vue, the licence is GPL-3.0, and the homepage is woonuxt.com.

Setup begins with a WordPress plugin, not with npm

The getting started sequence starts inside WordPress, and that ordering matters more than it might look.

You install the Settings for WooNuxt plugin from the WordPress plugin directory, then activate it and go to Settings and WooNuxt. That page installs all the required plugins for WooNuxt, adds some useful fields to the WPGraphQL schema, and automatically retrieves the WooCommerce payment gateway settings for Stripe and PayPal.

So the plugin is doing the tedious and failure-prone part: wiring up the WordPress side, extending the schema so the front end can ask for the data it needs, and pulling the payment configuration across so the checkout does not start from scratch.

Only after that do you configure the front end, with GQL_HOST and NUXT_IMAGE_DOMAINS, and the README points at the .env.example file for the details.

For local development you run the commands from the repository root, create .env from the example and then install and run.

bash
npm install
npm run dev

The dev server binds to localhost only. There is a separate dev:host script to expose it on your network, for example to test on a phone, and the README notes that Nuxt warns about this because the dev server has no authentication.

Static and ISR, and why the two hosts need different build commands

The deployment section is the most valuable part of the documentation, because the failure modes are specific and the fixes are precise.

Netlify uses a static Nuxt build together with the Netlify Image CDN, and the build command in netlify.toml is NUXT_IMAGE_PROVIDER=netlify NITRO_PRESET=static npm run generate, with the publish directory set to .output/public. The README says not to override those in the dashboard.

Vercel is different in a way that is easy to miss. It uses Nitro's Vercel server preset, so Vercel Image Optimization and the ISR route rules run at request time, and vercel.json builds with NUXT_IMAGE_PROVIDER=vercel NITRO_PRESET=vercel npm run build.

The publishing directory is the classic trap, and the README documents the symptom before the fix. If every /_nuxt JS and CSS request returns 404 and the HTML loads, the publish directory does not contain Nuxt's generated bundle, and the fix is to publish .output/public rather than dist. Publishing the dist folder instead serves prerendered HTML without the hashed bundle, which loads a blank or broken page.

For large catalogues, of ten thousand products and up, there is a third mode. You build with nuxt build rather than nuxt generate, product catalogue routes use Nitro routeRules with isr in nuxt.config.ts, and the default revalidation window is 3600 seconds, overridable through CATALOG_ISR_TTL. The first request to a route generates and caches the page, requests inside the window are served from cache, and after the window the next request serves stale content and triggers background regeneration.

On Netlify you need the server build mode for that to work, because static generate bypasses ISR entirely.

The image provider warning that breaks static deploys

One warning in the README deserves its own attention because it costs hours when you hit it.

Never set NUXT_IMAGE_PROVIDER=ipx on Netlify static hosting or any static export, because IPX needs a running Nuxt server. The guidance is to use netlify for Netlify, vercel for Vercel, and to reserve ipx for a self-hosted Nuxt server. When the variable is unset, WooNuxt uses Nuxt Image's portable none provider.

The underlying reason is architectural. Image optimisation in Nuxt is usually done by a server component that processes images on demand, which is exactly what you cannot have in a purely static output, since there is no server to ask. The platform specific providers delegate the work to the host's own image CDN instead, and the portable provider does nothing at all.

The environment file makes the choice explicit. The image provider override is optional and defaults to none, with the accepted values listed as netlify, vercel, ipx and none.

bash
NUXT_IMAGE_PROVIDER="netlify" 'vercel' 'ipx' 'none'

And the domains variable is where the second half of the image story lives. NUXT_IMAGE_DOMAINS takes hostnames only, comma separated, with no protocol, and the example shows a WordPress host alongside a CDN host.

A storefront that does not fetch a cart until you touch it

The session init performance section describes a design decision that most headless stores get wrong.

WooNuxt avoids loading the full WooCommerce session for every visitor on first paint, which keeps cached catalogue pages fast and reduces unnecessary WPGraphQL traffic, while still giving returning customers a responsive account and cart header.

The default flow has three cases. On an anonymous first visit, no backend session or cart call is made until the visitor interacts with the page. For a returning or logged-in user, WooNuxt detects existing auth and session cookies and makes a small immediate getCartSummary request, so the avatar and cart badge can appear quickly. And the full getCart request is loaded only when the customer actually needs it, such as opening the cart drawer, visiting cart, checkout or account routes, or changing cart contents.

The switch is storeSettings.initStoreOnUserActionToReduceServerLoad in the WooNuxt base layer's app.config.ts. The recommendation is to keep it enabled for high-traffic storefronts, and to disable it if the store prefers immediate full cart hydration over reducing backend calls.

That is a genuine trade-off rather than a free win, and the README is honest about which side of it a given store should pick. For a store with an unusual mix of logged-in and anonymous traffic, the setting is worth measuring rather than copying.

Customisation through Nuxt layers

The customisation story is built on the Nuxt layers feature, and the repository layout shows how that works in practice.

There is a woonuxt_base directory that is the parent Nuxt layer providing the WooNuxt storefront, and the README is explicit that it is not a separately runnable package. You add custom pages, components and configuration in the root project as a child layer, and the child overrides what it needs.

That is a clean extension model. The base is the storefront, and your project sits on top of it, so an update to the base can be pulled without your changes being lost in a merge. It is also the reason the base directory is a layer rather than a dependency: the two are applied in the order Nuxt expects, with the child winning.

The rest of the repository supports the same idea. nuxt.config.ts holds the Nuxt configuration, including the Nitro route rules for ISR, and netlify.toml and vercel.json hold the two host specific build setups. codegen.ts configures the GraphQL code generation, which runs before most other scripts through the pre hooks.

json
  "scripts": {
    "build": "nuxt build",
    "prebuild": "npm run graphql:codegen",
    "dev": "nuxt dev",
    "generate": "nuxt generate",
    "pregenerate": "npm run graphql:codegen",
    "postinstall": "nuxt prepare",
    "serve": "npm run generate && npx serve .output/public -l 8080"
  },

The pattern in those scripts is the thing to notice. Every command that needs types runs the GraphQL code generation first, so the generated query types are never out of date, and the postinstall hook runs nuxt prepare so a fresh clone works immediately.

Runtime versions, the GraphQL layer and the release cadence

The Node.js requirement is stated precisely, because Nuxt 4.6 requires ^22.22.3, or ^24.15.0, or 26.0.0 or newer. The README asks you to make sure your local, CI and hosting runtimes all use a supported version.

It also explains an absence. WooNuxt deliberately has no .nvmrc file and no package.json engines entry, and the guidance is to configure the Node.js version in your own environment rather than adding a repository pin unless your customization has a documented compatibility requirement. That is a deliberate choice about where the pin belongs, and it is one more thing for a host to get right.

The dependency list shows how the front end is put together. Nuxt 4.6 with Nuxt Image and Nuxt Icon, Tailwind CSS 4 with the Vite plugin, reka-ui for the component primitives, @vueuse/core for the composables, graphql-request with the graphql client, the Stripe JavaScript SDK, the Nuxt i18n module and the Vite PWA module. The GraphQL side uses the standard code generation tooling, with separate packages for the add, cli, typescript, typescript-graphql-request and typescript-operations plugins, and the generated types are what the typed queries use.

The releases are frequent and numbered in the four part style of a WordPress plugin. The recent tags are 4.29.3 from 2026-10-12, 4.29.1 from 2026-10-08 and 4.29.0 from 2026-10-07, and the last push was on 2026-10-17. The numbering mirrors the WooCommerce plugin conventions it lives alongside, which is convenient for the many store owners who track versions across both.

Editorial conclusion

Adopt WooNuxt when you run a WooCommerce store whose catalogue pages should be fast and indexable, and when you are willing to keep WordPress as the source of truth behind a GraphQL layer rather than moving the data. Do not adopt it if you need a fully dynamic store with no prerendered pages, because the whole design starts from a static build, and read the deployment section before you commit to a host, since Netlify and Vercel require different build commands and image providers. Before the first deploy, set GQL_HOST and NUXT_IMAGE_DOMAINS in .env from the example file, publish .output/public rather than dist, and check that your Node runtime satisfies the range Nuxt 4.6 requires, since the project deliberately ships no .nvmrc or engines field to catch you.

Frequently asked questions

How do I install WooNuxt for my WooCommerce store?

Install the Settings for WooNuxt plugin from the WordPress plugin directory, activate it, and configure your storefront under Settings and WooNuxt, which installs the required plugins, adds fields to the WPGraphQL schema and retrieves the Stripe and PayPal gateway settings. Then set GQL_HOST and NUXT_IMAGE_DOMAINS in your .env file.

Why does my static WooNuxt site show a blank page?

You are probably publishing the dist folder instead of .output/public. The symptom in the README is that the HTML loads but every /_nuxt JS and CSS request returns 404, because the publish directory does not contain Nuxt's generated bundle. Publish .output/public with npm run generate as the build command.

How do I enable ISR for a large product catalogue in WooNuxt?

Build with nuxt build rather than nuxt generate, and use Nitro routeRules with isr for the product catalogue routes in nuxt.config.ts. The default revalidation window is 3600 seconds and can be changed with CATALOG_ISR_TTL, and on Netlify you need the server build mode because static generate bypasses ISR.

Which image provider should I set for a static deployment?

Use netlify on Netlify and vercel on Vercel, and reserve ipx for a self-hosted Nuxt server because IPX needs a running server. Never set ipx on Netlify static hosting or a static export, and leaving the variable unset uses Nuxt Image's portable none provider.

How do I customise the WooNuxt storefront?

WooNuxt uses the Nuxt layers feature. The woonuxt_base directory is the parent layer that provides the storefront and is not a separately runnable package, and you add your own pages, components and configuration in the root project as a child layer that overrides what it needs.

Official sources

  1. License: GPL-3.0
  2. Project website
  3. README
  4. Releases
  5. scottyzen/woonuxt on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/scottyzen-woonuxt.svg)](https://hysenlabs.com/projects/scottyzen-woonuxt)

Was this useful?