Defining your content
Describe your collections, fields and identifiers in areca.config.ts, with the validation rules the SDK and CMS enforce.
Your content model lives in areca.config.ts, at the root of the website project. It lists the kinds of content your site has, such as articles or authors, and the fields editors fill in for each one. You push this file to the CMS with areca manifest push, and the CMS then shows the same collections and fields to editors.
In the CMS, a collection is called a content type. This guide uses "collection" throughout, because that is the name in the code.
The config file uses defineSiteContent. It checks the config at compile time, so your editor shows a mistake as you type it, and it returns the config unchanged. The rules are listed in authoring rules below.
An example: articles and authors
This example has two collections. Each article points to one author, which is a reference.
import { defineSiteContent } from '@areca-cms/site-sdk'
export default defineSiteContent({
siteKey: 'acme-site',
collections: {
authors: {
route: '/authors/$slug',
label: 'Authors',
fields: [
{ key: 'name', label: 'Name', type: 'text', required: true },
{ key: 'bio', label: 'Bio', type: 'textarea' },
{ key: 'photo', label: 'Photo', type: 'image' },
],
},
articles: {
route: '/blog/$slug',
label: 'Articles',
fields: [
{ key: 'title', label: 'Title', type: 'text', required: true },
{ key: 'excerpt', label: 'Excerpt', type: 'textarea' },
{ key: 'body', label: 'Body', type: 'richtext', required: true },
{ key: 'cover', label: 'Cover image', type: 'image' },
{ key: 'author', label: 'Author', type: 'reference', collection: 'authors' },
{
key: 'category',
label: 'Category',
type: 'select',
options: ['news', 'guides', 'updates'],
},
{ key: 'publishedOn', label: 'Published on', type: 'date' },
{ key: 'updatedOn', label: 'Updated on', type: 'date', after: 'publishedOn' },
],
},
},
})Areca adds a required slug field as the first field of every collection, so you do not need to declare one. Each entry's slug is used in URLs, and route tells the CMS where entries live on your site. See slug values.
Top-level options
| Option | Required | Description |
|---|---|---|
siteKey | Yes | The key of the CMS site, as shown on the site's Developer tab. areca init and areca manifest pull use it. The push does not send it, because the schema token already identifies the site. |
collections | Yes | An object whose keys are collection keys and whose values are collection definitions. It can be empty. |
globals | No | An object whose keys are site content section keys, such as companyInfo. Each section holds a single set of values, not a list. See site content. |
Collection options
| Option | Required | Description |
|---|---|---|
route | Yes | The frontend route pattern for entries, such as /blog/$slug. It must contain $slug, which is replaced by each entry's slug. It can be up to 500 characters. The SDK records the pattern for the CMS, but it does not generate routes. You still write the route in your framework. |
label | No | The name editors see in the CMS, such as "Articles". It can be up to 200 characters. If you omit it, the CMS shows the collection key. |
fields | Yes | The list of fields. A collection can have up to 100 fields. |
Field options
Each entry in fields is an object with these options:
| Option | Required | Description |
|---|---|---|
key | Yes | The identifier for the field. It is the name of the field's value in pulled data. In your code it becomes camelCase, so cover_image is coverImage. See identifiers. |
label | Yes | The label editors see. It can be up to 200 characters. |
type | Yes | One of the twelve field types, such as text, richtext or reference. See field types for each one. |
required | No | Set to true to require a value. Editors can save a draft without it, but the entry cannot be marked ready or go live until they fill it in. |
description | No | Help text shown to editors. It can be up to 1,000 characters. |
options | Only for select | The choices for a select field. Up to 200 options, each up to 200 characters. Other types do not accept it. |
collection | Yes for reference, otherwise not allowed | The key of the collection the reference can point to. It must be a collection key of the same config. Your editor suggests the keys as you type. |
after | Only for date and datetime | The key of another date or datetime field in the same collection. This value must be on or after that field's value. Your editor suggests only the keys of date fields. |
group | No, and only in site content | A heading shown above the field in the editor, such as Contact. Consecutive fields with the same heading share it. The SDK value stays flat. Collection fields may not set group. See site content. |
The SDK checks identifiers before it sends anything. The CMS validates the whole manifest when it receives it, including the length and count limits above.
Authoring rules
defineSiteContent enforces the first five rules with the TypeScript compiler, so your editor reports a mistake as you type. The last rule is checked when you push or pull:
typeis one of the twelve field types. Your editor suggests them.- Options depend on the type.
optionsis only allowed onselect.collectionis required onreference, and only allowed there.afteris only allowed ondateanddatetime. - References point at real collections. A reference's
collectionmust be the key of a collection in the same config. Your editor suggests those keys. afternames a date field. It must be the key of adateordatetimefield in the same collection. Your editor suggests only those keys.- Routes contain
$slug. A collection'sroutemust include the text$slug, so each entry has its own URL. - Keys are identifiers. The SDK checks them against the identifier rules when you push or pull, as described above.
import { defineSiteContent } from '@areca-cms/site-sdk'
export default defineSiteContent({
siteKey: 'acme-site',
collections: {
authors: {
route: '/authors', // error: a route must contain $slug
fields: [{ key: 'name', label: 'Name', type: 'text', required: true }],
},
articles: {
route: '/blog/$slug',
fields: [
{ key: 'author', label: 'Author', type: 'reference', collection: 'writers' }, // error: no collection called writers
{ key: 'category', label: 'Category', type: 'text', options: ['news'] }, // error: options only on select
{ key: 'updatedOn', label: 'Updated on', type: 'date', after: 'title' }, // error: title is not a date field
],
},
},
})Identifiers
Identifiers are the names you choose for collections and fields: the keys of collections, the key of each field, and any collection or after value that points to another one. They have these rules:
- They start with an ASCII letter. After that they can contain letters, digits,
_and-. - They are at most 64 characters long.
- They must not be a reserved name. The reserved names are
__proto__,prototype,constructor,manifest,con,prn,aux,nul,com1tocom9, andlpt1tolpt9. The check ignores case, soMANIFESTis reserved too. - A collection key or site content key must not be
resolve,href,preview,globalsorpreviewGlobals. Camel-cased forms count too, sopreview-globalsis refused. The content object in your code uses those names for its own methods. This check ignores case. Field keys may use these names. - A field key must be unique within its collection.
- In your code, keys are camelCase, so two keys that differ only in their dashes or underscores (
blog-postsandblog_posts) collide. The pull refuses them. See typed content.
Identifiers are also used as names in the output. Each collection becomes a file named after its key, such as articles.json. For that reason, pick names that you will keep.
Two rules follow from this:
- Renaming a collection key creates a new collection. The old one is disabled on the next push. Its entries stay in the CMS but are no longer published.
- Renaming a field key does not move values. Existing values stay under the old key, and the new field starts empty. Editors need to re-enter the value.
If an identifier breaks the rules, areca manifest push stops with an error such as Unsafe collection or field identifier, and it does not send the manifest.
Slug values
Entries and slug fields have a second, separate rule: the value must be lowercase letters and digits, with single hyphens between parts. There are no leading or trailing hyphens, and the value can be up to 200 characters. Examples: hello-world, 2026-roadmap.
Site content sections
Site content sections go under globals, beside collections. They use the same field options, with two differences: a section has no slug field, and a field may set group. A section can also set label, seo (default false) and previewPath. See site content for the full example and rules.
Changing the config
Edit areca.config.ts and run areca manifest push. The push replaces the definition of each collection or site content section it lists, and it disables any it leaves out. Disabled sections keep their content. For what happens to existing content, see syncing the schema.
If your collections were created in the CMS, you can copy them into a config file with areca manifest pull. See CLI reference.
Related
- Field types: every field type, its options and the values it produces.
- Syncing the schema: push the config and understand what changes.
- Reading content: use the typed entries in your site.
- Site content: single sections of values, such as company details.