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.
What you can do here
Section titled “What you can do here”The home view
Section titled “The home view”/admin/cms shows a card for each known collection plus a “Create Collection” card. Cards come from three sources:
- Registered schemas in
caret()config - Dynamic collections created through Studio
- 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.
Editing an entry
Section titled “Editing an entry”Inside a collection, you see a list of entries. Click one and Studio renders a form generated from the schema:
| Field type | Renders as |
|---|---|
string | Text input (long strings get textareas) |
number / integer | Number input with min/max |
boolean | Toggle |
enum | Select dropdown |
object | Grouped section with nested controls |
array | Repeatable rows with add/remove |
format: url / email | Input 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.
Draft, preview, and publish
Section titled “Draft, preview, and publish”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.
| Action | Where | What happens |
|---|---|---|
| Save / inline edit | Editor toolbar or Studio | Writes to draft overlay |
| Preview | Editor toolbar | Toggle to see draft content on the live page |
| Publish | Editor toolbar | Flushes draft overlay into base storage |
| Discard | Editor toolbar | Drops 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.
Git commit on publish
Section titled “Git commit on publish”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.
Revision history
Section titled “Revision history”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.
Creating a new entry
Section titled “Creating a new entry”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.
Reordering
Section titled “Reordering”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.
Schema sources
Section titled “Schema sources”Studio determines field types and labels from one of three sources, in priority order:
- Registered —
caret({ schemas: {...} }) - Dynamic — created via Studio’s collection builder
- 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.
API calls behind the UI
Section titled “API calls behind the UI”Everything Studio does is a public API call you can reproduce from a script:
| Route | Purpose |
|---|---|
GET /api/cms/entries?collection=... | List entries |
GET /api/cms/schema?collection=... | Schema + template |
GET /api/cms/collections-metadata | All dynamic collection metadata |
POST /api/cms/mutate | Execute a mutation command |
POST /api/cms/publish | Flush draft overlay to base storage |
DELETE /api/cms/draft | Discard draft without publishing |
GET /api/cms/history?collection=...&id=... | Revision history |
POST /api/cms/upload | Upload an image or asset |
See API Reference for full payloads.
Example mutation
Section titled “Example mutation”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 }'