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.

When a collection has no entries yet, Studio shows adapter-agnostic guidance — run Caretize to tag templates or create an entry from inline editing.

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.

Inline edits and Studio saves go into a per-editor draft overlay first. Published storage (.caret/data/ or src/content/*.md) does not change until you click Publish in the editor toolbar.

ActionWhereWhat happens
Save / inline editEditor toolbar or StudioWrites to draft overlay
PreviewEditor toolbarToggle to see draft content on the live page
PublishEditor toolbarFlushes draft overlay into base storage
DiscardEditor toolbarDrops draft without touching published content

After Publish on static delivery sites, run astro build (or let CI rebuild via delivery.publish.webhookUrl) so visitors see the update.

Set CARET_GIT_ON_PUBLISH=true in the environment where authoring runs. After a successful publish, CaretCMS best-effort commits the storage path (filesystem or markdown content root) with a message like publish pages/home. Git failures never block publish.

Each save creates a revision snapshot you can restore from the history panel. Prior versions show timestamps and action labels (save, put, delete, reorder, restore). Restoring loads that version into the editor — save again to make it current.

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
POST /api/cms/publishFlush draft overlay to base storage
DELETE /api/cms/draftDiscard draft without publishing
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
}'