The layer chain
You don't fork the storefront. A theme is a Nuxt 4 app that extends a published base layer:
export default defineNuxtConfig({
extends: ['@revenexx/cover'],
})
@revenexx/cover is on public npm. Extending it gives you the whole storefront — components, composables, and the server routes that talk to the platform — and overriding any part of it is plain Nuxt layer shadowing. No patching, no ejecting, no vendored copy to keep in sync.
The two chains
There are two shapes in practice, and the difference is whether you inherit the block library.
Custom theme, no block library:
your-theme → @revenexx/cover
Full page-builder theme:
your-theme → @revenexx/cover-theme → @revenexx/cover
Extending @revenexx/cover-theme gives you both layers, because cover-theme extends cover itself.
What each layer provides
| Layer | What it brings |
|---|---|
@revenexx/cover | The storefront foundation: the design-system components, the commerce composables (useProducts, useOffers, useCartStore, useSearch, the account family), the /api/* server routes that reach the platform, the service registry with its mock implementations, i18n messages, and the FormKit configuration. |
@revenexx/cover-theme | The Blökkli layer on top: around ninety block bundles, the editor adapter, the block renderer, the /admin/edit editor route, the shareable-preview route, and the editor add-ons. It also sets rootId: 'nuxt-root' for you. |
| your theme | The manifest, your brand, your own blocks, and any override of the two layers below. |
Which one to extend
Extend @revenexx/cover-theme if the customer's content team should compose pages visually. You inherit the block library and the editor wiring, and your work is adding brand-specific blocks and overriding the ones that don't fit. This is the normal choice for a commerce storefront, and it's what a scaffolded theme does.
Extend @revenexx/cover directly if you want the commerce foundation but intend to build your own page structure — a fixed set of hand-written routes rather than editor-composed pages. You keep the composables and server routes and skip the editor entirely. If you go this way, remember to set rootId: 'nuxt-root' yourself if you later add the editor.
The chain is ordinary Nuxt
Nothing about this is revenexx-specific machinery. extends is Nuxt's own layers feature: each layer contributes app/, server/, public/ and configuration, and the closest layer wins for any given file path. That means the override mechanism is Nuxt's, the aliasing is Nuxt's, and anything you know about Nuxt layers applies here.
Two consequences worth knowing up front:
- Resolution order runs from your theme outwards. A file in your project shadows the same path in
cover-theme, which shadows the same path incover. - Config is merged, not replaced. Your
nuxt.config.tsadds to what the layers declared;app.config.tsmerges key by key, which is exactly how the service modes switch works.
Keeping up with the layer
Because the base layer is a published npm package, you upgrade it like any dependency — bump the version and rebuild. Your overrides keep working as long as the file paths they shadow still exist, which is the one thing to watch on a major bump.
Anything you override is a deliberate maintenance commitment. Before shadowing a component, check whether a design token or a block option gets you there instead: token changes survive upgrades for free.
Next steps
- Overriding the base layer — file-path shadowing and the deep-import map, with a real before and after.
- Service modes — the
app.config.tsmerge that flips a domain from mock to live. - Theme anatomy — the manifest that sits alongside the Nuxt app.
- Starting points — the three ways to begin a project.