Model your content
A content type is the shape of a piece of content: which fields it has. You define it in the dashboard, with no code. Usually your agent does it in step 2; this guide explains what it does, so you can review it or do it by hand.
Create a content type
In your site, go to Model → New type:
| Field | What it is | Example |
|---|---|---|
| Name | How people see it | "Event" |
| API ID | How the API asks for it. Lowercase letters, numbers and underscores; starts with a letter | event |
| Description | Optional. Your agent reads it to know what the type is for | "Events on the school calendar" |
| Singleton | Whether it has a single entry. For site settings | site_settings |
The API ID can't be changed later: your site already uses it to fetch the content.
Agent guidance
Each type can carry instructions for whoever adds content, a person or your agent. You edit them on the type's page, under Agent guidance:
- When to use it and when not to. One or two sentences. "Use Pricing for tuition and fees. Not for event lists." Up to 2000 characters.
- What it looks like. Up to 4 previews of the site, picked from your files. They must be images.
- Help per field. One line: format, unit or example. "In USD, no symbol: 12500".
Your agent reads them before creating anything, in describe_space in the MCP and in your site's llms.txt. Over the API they come in guidance, previews and fields[].help on each content type. They help most when there are several similar types, like the sections of a page: without guidance, the agent guesses which one to use. See Composable pages.
Page URL
Tell Pluma where each entry of the type lives on your site: /blog/{slug}, /events/{id}. With it, every entry gets View live and View on staging links, and the API returns its sys.url. See Staging and previews.
Add fields
Each field has a name, an API ID, a type, and three options:
- Required: an entry can't be published without this field.
- Localized: it has one value per locale. If not, the same value applies to all of them.
- Title field: the one shown in lists. One per type.
Field types
| Type | API | What it stores | Example |
|---|---|---|---|
| Short text | symbol |
Up to 256 characters | Title |
| Long text | text |
Plain text with no limit | Summary |
| Rich text | rich_text |
JSON blocks: paragraphs, headings, lists, images. The API also returns it as markdown and HTML | Post body |
| Integer | integer |
42 | Seats |
| Decimal number | number |
3.5 | Price |
| Yes / no | boolean |
true or false | Featured |
| Date | date |
Date only (2026-08-14), date and time with its time zone (2026-10-12T09:00:00-06:00) or without a zone (2026-10-12T09:00:00). Stored as is, not converted to UTC |
Event date |
| JSON | json |
Any JSON object | Extra data |
| Slug | slug |
Lowercase letters, numbers and hyphens. Unique within the type | open-house |
| Tags | tags |
List of short texts | ["families", "2026"] |
| Reference | reference |
Another entry. Can be limited to certain types (even types you haven't created yet) | The post author |
| References | references |
Several entries | Related posts |
| File | asset |
An image or document | Cover photo |
| Files | assets |
Several | Gallery |
| List | list |
Rows of simple item fields, in order. See Lists | Menu, opening hours, social links |
Lists
For things that are rows of the same small shape: the site menu (label, url), opening hours (days, open, close), social links (network, url). Each row is edited as a row in the dashboard, with add, move up and remove, instead of raw JSON.
- A list has 1 to 10 item fields. Each has an
api_id, anameand a type:symbol(default),text,integer,number,booleanordate. - Up to 100 rows. Empty rows are dropped when saving. The order you see is the order you get.
- In the dashboard, when you add a field of type List, write the item fields separated by commas:
Label, URLorDays, Open, Close, Closed:boolean. - By API or MCP, define them with
item_fieldsand send the value as a list of objects:
{ "api_id": "navigation", "name": "Menu", "type": "list",
"item_fields": [ { "api_id": "label", "type": "symbol" }, { "api_id": "url", "type": "symbol" } ] }
{ "fields": { "navigation": [ { "label": "Menu", "url": "/menu" }, { "label": "Visit", "url": "/visit" } ] } }
A row with a key that isn't an item field is rejected, with the name of the field it expected. If each row needs its own page, a photo or references, use a content type of its own instead.
Rules that protect your content
- Deleting a field doesn't delete data. The field is hidden and the data stays in each entry's previous versions.
- Changing the type of a field that already has data is rejected, with a message that explains how to migrate: create a new field, copy the data, and hide the old one.
- An API ID is never reused within the same type, even if the field is hidden.
- A type with entries can't be deleted until you archive them.
Possible errors
| Message | What to do |
|---|---|
| "That API ID already exists in this site" | Choose another one, or use the type that already exists. |
| "The API ID must start with a letter and contain only lowercase letters, numbers and underscores" | blog_post works; Blog-Post doesn't. |
| "You can't change the type of a field that has data" | Create a new field and hide the old one. |