Local development
A theme is a Nuxt 4 app, so the dev loop is the standard one. This page covers the revenexx-specific parts: what runs without credentials, which environment variables exist, and the one configuration line the visual editor depends on.
Run it with no credentials
Start here, because it saves the most time.
npm install
npm run dev
That's it. You get a working storefront with a catalog, a cart, and a checkout — no API key, no tenant, no environment variables. Onboarding a developer onto a theme project is a clone and an install.
The reason is the service registry: every commerce and pages domain resolves through a key that defaults to mock, served from bundled fixture data. When you need real data, flip only the domains you care about to api in your own app.config.ts, or switch at runtime with the dev panel. That per-domain granularity is deliberate — you can run live products against a mocked cart while you build the product pages, and you never have to choose between "all mocks" and "full production wiring".
Full explanation, including the domain list: Service modes.
Ports
nuxt dev serves on port 3000 by default. A theme that has to run alongside other services usually pins its own:
{
"scripts": {
"dev": "nuxt dev --port 3004",
"build": "nuxt build",
"generate": "nuxt generate",
"preview": "node .output/server/index.mjs"
}
}
Two things to know about the port:
- The visual editor is embedded from Cockpit, which loads your
/admin/editroute in an iframe. When you develop the editor experience against a local theme, the URL Cockpit points at has to include the port you're actually serving on. npm run previewruns the real production server —node .output/server/index.mjs, exactly what the platform runs — and defaults to port 3000 regardless of your dev port. Use it to check the built output before you deploy.
Environment variables
A theme reads its platform connection from Nuxt's runtime config, which means every value has a NUXT_-prefixed environment variable.
| Variable | What it sets | Default |
|---|---|---|
NUXT_REVENEXX_API_URL | The gateway to call | https://api.revenexx.com |
NUXT_REVENEXX_TENANT | The tenant slug requests are scoped to | — |
NUXT_REVENEXX_API_KEY | The API key the server routes authenticate with | — |
NUXT_CHECKOUT_SESSION_SECRET | Signing secret for the stateless checkout session token. Set it explicitly on any deployment serving more than one tenant. | — |
NUXT_PUBLIC_CART_INACTIVITY_TTL | How long an idle cart survives, in milliseconds | 31 minutes |
NUXT_PUBLIC_TAX_INCLUDED_PRICES | Whether displayed prices include tax | false |
NUXT_PUBLIC_* values reach the browser. NUXT_REVENEXX_API_KEY and NUXT_CHECKOUT_SESSION_SECRET are private runtime config, readable only server-side. Never move them under runtimeConfig.public, and never pass the key to a component. See The BFF pattern.Put them in a .env file for local work:
NUXT_REVENEXX_API_URL=https://api.revenexx.com
NUXT_REVENEXX_TENANT=acme
NUXT_REVENEXX_API_KEY=...
A scaffolded theme ships a .env.example listing credential names only — never values. Keep it that way, and keep .env out of Git.
These are the variables your theme reads. A deployed site also receives a set of REVENEXX_SITE_* variables the platform injects, including a scoped API key issued to that site's runtime — which is why you generally don't provision a key by hand for production. See Environment variables.
The visual editor needs rootId: 'nuxt-root'
The Blökkli editor anchors its artboard to the element with id nuxt-root. Nuxt's default root id is __nuxt, so a theme must rename it or the editor cannot attach — it fails with a "failed to locate root element" error rather than degrading.
export default defineNuxtConfig({
app: {
rootId: 'nuxt-root',
},
})
Themes extending @revenexx/cover-theme inherit this. If you build directly on @revenexx/cover, set it yourself.
The editor itself runs at /admin/edit?page=<page-id> inside your theme, which is what makes the editing experience trustworthy: an editor is looking at your real components rendering real props, not an approximation. That route is the only place the editor bundle is loaded — live pages never carry it.
Rendering mode
A revenexx theme is always server-rendered: price, stock, and the buyer's session are per-request facts. The site's rendering strategy is its adapter, part of the build settings, and if you don't set it the platform detects it from your build output.
The full comparison, and the per-framework configuration for both modes, is in Rendering.
Project dependencies
Dependencies install during the build, using the site's install command. Two rules:
- Commit your dependency manifest and lockfile. The build installs from the public registry, so every dependency must resolve there.
- Do not commit
node_modules. Packages built for your local OS may not work in the build environment, and you'll be debugging a machine mismatch instead of your code.
The install and build commands themselves belong to the site rather than to a file in your repository — see Build configuration.
Check the production build before you deploy
Dev mode runs against mocked services and an unminified bundle, which hides a whole class of problem. Before pushing, run the build the way the platform will:
npm run build # → .output
npm run preview # serves .output/server/index.mjs
Then view source on a page to confirm it really server-renders, rather than trusting the rendered result.
Related
- Service modes — mock to live, one domain at a time
- Rendering — SSR and static, and per-framework configuration
- Frameworks — the fifteen supported frameworks and adapter detection
- Environment variables — what a deployed site receives
- Build configuration — install command, build command, output directory
- Build your first theme — the hands-on tutorial