The app manifest, field by field
The manifest is cartbase.app.json at the root of the app folder. The
platform validates it on cartbase app validate and cartbase app deploy;
a refused manifest answers one row per problem, the path and what to change.
Unknown keys are refused by name. This page is generated from the schema
the platform validates with, so it cannot drift. The JSON Schema for
editors is app-manifest.schema.json, also at
https://docs.cartbase.ai/app-manifest.schema.json.
Top level
| Field | Required | What it is |
|---|---|---|
key |
yes | The app's slug: 2 to 40 characters, lowercase letters, digits and hyphens, starting with a letter. The URL segment under Apps and the prefix of every record type. Reserved: reviews, documents, nra-audit, subscriptions, feeds, search, search-discovery, design-system, new, install, validate, settings. |
name |
yes | The name shown in Apps, up to 60 characters. |
description |
yes | One line saying what the app does, up to 140 characters. |
version |
yes | Three numbers, 1.0.0. Every deploy is kept under its version. |
icon |
no | One of apps, pin, pages, star, tag, chart, users, cart, invoice, dollar, rss, search, van, warehouse, bell, swatches, discount, home, cog. Default apps. |
records |
no | The app's record types, up to 20. See below. |
settings |
no | What the merchant fills on the app's Settings screen, up to 40. See below. |
screens |
no | The screens under the app, up to 8. Omitted: one records screen per record type, then Settings when settings exist. |
storefront |
no | { files: [...], component? }: the files the app adds to the storefront project, relative to its root, up to 200. Recorded so an uninstall removes exactly them. |
permissions |
no | Must be empty in this version: an app writes only its own records. |
A record type
{
"type": "location", // snake_case, up to 40 characters, letters first
"name": "Location", // singular, what a record page is called
"name_plural": "Locations", // the list's title; default: name + "s"
"visibility": "public", // public | private; default public; fixed for life
"fields": [ { "key": "city", "name": "City", "kind": "text", "required": true } ]
}The platform stores the records as its own metaobjects, owned by the app:
the store type is <key>.<type>, so store-locator.location. A
public type answers at GET /api/store/metaobjects/<key>.<type> with the
publishable key (active records only); a private type never leaves the
admin. Visibility cannot change after the first deploy: declare a new type
and move the records.
A field
| Field | Required | What it is |
|---|---|---|
key |
yes | snake_case: lowercase letters, digits, underscores. Unique in the type. |
name |
yes | The label the merchant reads. |
kind |
yes | One of text, rich_text, number, boolean, date, file, color, reference_product, reference_collection, reference_page, reference_metaobject. |
required |
no | Enforced when a record is or becomes active; drafts may be incomplete. |
validations |
no | { min?, max? } (text: length, number: value), pattern? (text, a regex), metaobject_definition_id (required for reference_metaobject). |
Changing fields on a later deploy follows the platform's own rule: adding is free; removing a field or changing its kind is refused while records carry a value for it; making a field required is refused while an active record lacks it. Clear or migrate the records first.
A setting
{
"key": "maps_key", // snake_case, letters first
"name": "Maps API key",
"description": "From your maps provider's console",
"kind": "secret", // text | number | boolean | select | secret
"required": false,
"options": [ { "value": "light", "label": "Light" } ], // select only
"default": "light" // not for secret; must match the kind
}A secret is written on the app's Settings screen, stored encrypted by the
platform, never sent to a browser, and handed only to the app's own call at
GET /api/apps/me with the app's key.
A screen
{ "kind": "records", "key": "locations", "label": "Locations", "record": "location" }
{ "kind": "settings", "key": "settings", "label": "Settings" }A records screen names a declared record type. A settings screen needs at least one declared setting. Keys are slugs and unique.