Skip to content

Content Studio

Content Studio is the structured admin UI at /admin/cms. Use it when click-to-edit isn’t enough — when you need to browse all entries, manage relationships, edit hidden fields, or restore from history.

/admin/cms shows a card for each known collection plus a “Create Collection” card. Cards come from three sources:

  1. Registered schemas in caret() config
  2. Dynamic collections created through Studio
  3. Discovered collections (anything with at least one entry on disk)

Click a collection card to drill into its entries.

Inside a collection, you see a list of entries. Click one and Studio renders a form generated from the schema:

Field typeRenders as
stringText input (long strings get textareas)
number / integerNumber input with min/max
booleanToggle
enumSelect dropdown
objectGrouped section with nested controls
arrayRepeatable rows with add/remove
format: url / emailInput with validation

Save with the button at the top right. Studio uses optimistic locking — if someone edited the entry while you were typing, you get a conflict toast and a “Reload to see latest” button.

Every save snapshots the previous state. Open the history panel to see prior versions with timestamps and action labels (save_field, put_entry, etc.). One click restores any prior version into the editor; you still need to save to commit.

If a collection’s schema is marked creatable: true, Studio shows a “New entry” button. Clicking it spawns a blank entry from the schema template. Required fields are flagged; you can’t save until they’re filled.

For collections without creatable: true (typical for site::global style singletons), Studio hides the new-entry button.

If the schema is marked orderable: true, the entry list becomes drag-handle reorderable. The new order is persisted via a reorder_entries mutation. Useful for blog-post lists, navigation items, repeating sections.

Studio determines field types and labels from one of three sources, in priority order:

  1. Registeredcaret({ schemas: {...} })
  2. Dynamic — created via Studio’s collection builder
  3. Inferred — guessed from the first stored entry

The schema endpoint (/api/cms/schema?collection=pages) returns a source field telling you which one was used. See Schemas for the full picture.

Everything Studio does is a public API call you can reproduce from a script:

RoutePurpose
GET /api/cms/entries?collection=...List entries
GET /api/cms/schema?collection=...Schema + template
GET /api/cms/collections-metadataAll dynamic collection metadata
POST /api/cms/mutateExecute a mutation command
GET /api/cms/history?collection=...&id=...Revision history
POST /api/cms/uploadUpload an image or asset

See API Reference for full payloads.

curl
curl -X POST http://localhost:4321/api/cms/mutate \
-H 'Content-Type: application/json' \
-H 'x-caret-request: 1' \
-H 'Cookie: caret_session=<your-token>' \
-d '{
"type": "save_field",
"collection": "pages",
"id": "home",
"field": "hero.headline",
"value": "Ship faster with CaretCMS",
"expectedRevision": 7
}'