Local development

The dev loop for a theme — running with no credentials, the NUXT_* runtime variables, choosing a port, previewing the production build, and the rootId the visual editor requires.

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.

Bash
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:

package.json
{
  "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/edit route 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 preview runs the real production servernode .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.

VariableWhat it setsDefault
NUXT_REVENEXX_API_URLThe gateway to callhttps://api.revenexx.com
NUXT_REVENEXX_TENANTThe tenant slug requests are scoped to
NUXT_REVENEXX_API_KEYThe API key the server routes authenticate with
NUXT_CHECKOUT_SESSION_SECRETSigning secret for the stateless checkout session token. Set it explicitly on any deployment serving more than one tenant.
NUXT_PUBLIC_CART_INACTIVITY_TTLHow long an idle cart survives, in milliseconds31 minutes
NUXT_PUBLIC_TAX_INCLUDED_PRICESWhether displayed prices include taxfalse
Only the 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:

.env
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.

nuxt.config.ts
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:

Bash
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.

Was this page helpful?