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.