cockpit.json reference
cockpit.json declares the operator UI your app adds to Commerce Studio. If your app is a pure API service with no operator screens, you do not need the file at all.
Point your editor at the schema
{
"$schema": "https://schemas.revenexx.com/cockpit.schema.json"
}
The schema is public, large and precise. It is faster than reading any page, including this one — use it for autocompletion and validation, and use these pages for the parts a schema cannot tell you: which values are exercised, what a renderer actually does, and where the sharp edges are.
The four top-level keys
{
"$schema": "https://schemas.revenexx.com/cockpit.schema.json",
"navigation": [ ],
"views": [ ],
"widgets": [ ],
"action_buttons": [ ]
}
| Key | Adds | Status |
|---|---|---|
navigation | Sidebar entries in the hosting studio | In production use |
views | Page-level routes, each a list, detail or form | In production use |
widgets | Cards on the Cockpit dashboard | In production use |
action_buttons | Buttons injected into another app's entity views | Declared, unexercised |
Most apps use navigation and views and add a couple of widgets.
action_buttons is in the schema and no shipped app uses it. You name a target_entity, and when the Cockpit renders that entity's view your button is meant to appear in its toolbar. Required fields are label, target_entity and kind (navigate, api or link).The mechanism is declared but unexercised, so there is no production example to point at and no behaviour that can be described with confidence. Treat it as ground to try and verify, not as a documented feature. If cross-app UI is what you need, the reliable route today is parent anchoring — contributing a page under another app's heading.Localisable strings
Anywhere the schema calls for operator-facing text — a label, a title, a description, a confirmation, a success message — you may write either form:
"label": "Suppliers"
"label": { "en": "Suppliers", "de": "Lieferanten" }
| Rule | |
|---|---|
| Plain string | Shown in every UI language. Stays valid forever; no manifest has to be converted. |
| Map | Keys are BCP-47 language tags. en is required and is what the Cockpit falls back to when its UI locale has no entry. |
| Blank values | Not allowed — every entry must hold at least one non-blank character. |
So a half-translated manifest degrades to English rather than to a blank label.
Views
Each view declares a route, a type and the entity it works on.
"views": [
{ "route": "/suppliers", "type": "list", "entity": "suppliers", "columns": [] },
{ "route": "/suppliers/:id", "type": "detail", "entity": "suppliers" },
{ "route": "/suppliers/new", "type": "form", "entity": "suppliers", "mode": "create" },
{ "route": "/suppliers/:id/edit", "type": "form", "entity": "suppliers", "mode": "edit" }
]
list, detail and form are the only view types. That four-view set per entity is what every shipped app declares.
| Type | Required keys | Page |
|---|---|---|
list | route, type, entity, columns | List views |
detail | route, type, entity | Detail views |
form | route, type, entity | Forms |
Routes use :param placeholders and are mounted under the hosting studio, so /suppliers becomes /commerce/suppliers. Declare the studio-relative path.
Every view kind accepts a permissions array — see Permissions and scope.
The type vocabularies at a glance
Four closed lists shape most of the file. Each is covered in full on its own page.
26 column types — List views:
text number money boolean date datetime
badge image relation media media-collection
markets toggle default-flag meter progress
count template quantity identity relative-time
country-list flag string-list record-list localized-text
34 field types — Forms:
text textarea number money boolean date
datetime select multi-select relation reference
json image email url tel media
media-collection localized-text rules fieldset
record-list string-list key-value record-view editor-link secret
address measure price market-assignment
tree-assign line-selection
Filter types — List views:
text select multi-select boolean date-range
11 action kinds — Actions and writes. Four of them are in production use; the other seven are supported but unexercised.
What the file is not
- Not a place for components. There is nothing to export and no bundle.
- Not the source of your data model. That is
schema.json. - Not the source of your routes. That is
manifest.capabilities.json. Awriteor anapiaction naming an endpoint no capability serves gives the operator a404after they click. - Not where merchant configuration lives. That is
settings.json, which the Cockpit renders as a form on its own.
Practical guidance
Claim one top-level nav entry, not one per page. A nav entry is the way into your app; detail and form views are reached from the list. The sidebar is a shared resource, and every extra entry is one an operator scans past to reach somebody else's app.
Declare sort on anything called "recent". A list without an explicit sort shows whatever the database returned first, which is not the same as newest.
Use vocabulary on any select or badge whose values a merchant can extend. A hard-coded options list cannot offer a value the merchant created after you wrote the file.
Let the renderer write, unless it genuinely cannot. Reach for write only when the change has a side effect the database cannot produce on its own.
Where to go next
- Navigation — the four group keys, anchors, hosted tabs, badges, icons.
- List views — columns, filters and everything a list can do.
- Detail views — sections, tabs, children, metrics.
- Forms — modes, fields, steps, constraints.
- Widgets — the two dashboard renderers.