Preview locally

Render your cockpit.json in the real Commerce Studio on your own machine with @revenexx/studio-commerce-devkit — mock data from your schema, and a functions console that runs your code against a simulated gateway.

@revenexx/studio-commerce-devkit is published on the public npm registry and boots the same Commerce Studio module the Cockpit runs, against mock data generated from your app's schema.json. No platform, no backend, no auth, no account.

This is the loop that is fully available to you today.

Install and run

The devkit needs Node.js 22.12 or newer, because Nuxt 4 and Vite 7, which it runs on, require it. The devkit does not declare this itself, so npm does not warn you on an older Node (as of devkit 0.1.11).

Terminal
cd my-commerce-app          # the directory holding cockpit.json
npm i -D @revenexx/studio-commerce-devkit
npx commerce-studio

Open the page of one of your views, such as http://localhost:3030/commerce/suppliers for a view whose route is /suppliers. The sidebar lists your app, and its list, detail, form and widget views render from cockpit.json.

Do not start at /commerce. The dashboard there fails to load in devkit 0.1.11 with "does not provide an export named 'default'", and the browser shows a 500 (as of 2026-10). List, detail and form pages of a view render; only the dashboard page was seen failing.

pnpm and yarn work the same way — pnpm add -D @revenexx/studio-commerce-devkit && pnpm commerce-studio.

Environment variableEffect
PORTChange the port. Default 3030.
APPS_DIRWhich directory the apps are read from. Defaults to your current directory.
NUXT_STUDIO_BUILDDIRWhere the preview's build output goes. Defaults to .commerce-studio/ in your project — gitignore it.

Preview a whole set of apps at once by pointing APPS_DIR at their parent:

Terminal
APPS_DIR=/path/to/apps npx commerce-studio

The loop

  1. Edit cockpit.json — navigation, list, detail, form or widget views.
  2. Edit schema.json — entities and columns, which drive the mock data.
  3. Reload the page. The manifests are re-read from disk per request, so there is no rebuild and no restart.
  4. Iterate. The same cockpit.json renders identically in the real Cockpit, because this host runs the exact same module.

What the mock data is built from

The preview reads your schema.json and generates plausible rows generically:

DeclarationBecomes
A column typeA value of that shape — text, number, boolean, timestamp, uuid, jsonb
A check with an in (…) listThe set of values that column cycles through — so a badge column and a select field show real options
A references entryA real id taken from the referenced entity's own mock rows, so relation columns and pickers resolve
notNull and defaultNothing for the seeded rows, which are never null. default fills a column on rows you create through the functions console
schema.json
{
  "$schema": "https://schemas.revenexx.com/schema.schema.json",
  "entities": {
    "suppliers": {
      "columns": {
        "id": { "type": "uuid", "pk": true, "default": "gen_random_uuid()" },
        "code": { "type": "text", "notNull": true },
        "name": { "type": "text", "notNull": true },
        "status": { "type": "text", "notNull": true, "default": "'active'",
          "check": "status in ('active', 'paused', 'retired')" },
        "created_at": { "type": "timestamptz", "notNull": true, "default": "now()" }
      }
    }
  }
}

Creates, edits and deletes persist in memory for the session and are regenerated when the server restarts. It is for seeing the UI, not for persistence.

The functions console

Open /functions from the top strip to run your app's server-side code locally against a simulated API gateway.

It lists your app's routes from manifest.capabilities.json. Pick one, fill in the path params, the query and a JSON body — prefilled from the request schema — and Send. You get the real response: status, JSON, timing, and the function's log output.

How it works:

  • Each app is one function at src/main.js. The simulated gateway builds a request context, requires the module and invokes it.
  • The function's data adapter is pointed at the same mock store the views read. So you create a supplier through POST /suppliers in the console, then see it in the /commerce list.
  • Cross-app calls run locally too. A function's gateway client is pointed back at this host and the real /v1/<app>/… path scheme is served, so a multi-app flow is forwarded to the other apps' functions against the same store.

Two requirements:

  • The app's own dependencies must be installed, since the preview requires your function.
  • Every participating app in a cross-app flow needs its dependencies installed too, since each one is required and run.

Edits to src/main.js are picked up on the next run.

What is stubbed

The standalone host has no Storage or import/export service behind it, so two things are deliberately inert:

SurfaceStandalone behaviour
A media / media-collection fieldThe picker does nothing. The real Storage picker is Cockpit-only.
A view's io (import/export) blockNot offered.

Both work in the real Cockpit. Do not treat their absence here as a manifest error.

Troubleshooting

SymptomCause
Empty sidebar, no appsAPPS_DIR points somewhere without a cockpit.json.
A list view renders but is emptyThe entity has no columns in schema.json, or a check / references the generator could not satisfy.
A nav entry does not appearThe entry has neither a route nor children, so it has nothing to show and is dropped.
A nav entry appears in the wrong sectiongroup is not one of the six recognised keys — see Navigation.
An icon is a generic boxThe Solar icon name did not resolve. A typo shows as the fallback icon rather than as a blank sidebar.
An api action returns 404The endpoint has no matching capability in manifest.capabilities.json.

Where to go next

Was this page helpful?