Skip to main content

Content Types

A content type is the shape of a kind of entry. Every entry has exactly one content type; the type defines the fields, the publishing semantics, and where in the tree the entry can live.

Type flags

FlagEffect
isRoutableEntry has a URL. Publishing writes a row to RouteIndex.
isPublishableEntry can be published / unpublished. Folders typically have this off.
isSingletonReserved / not yet enforced. A schema column only — no API sets it and nothing enforces a single-entry limit today. Intended for site-settings rows in a future release.

allowedChildTypes

Constrains which content types can be created as children of a node in the tree. Two layers, with the per-node TreeNode.allowedChildTypes override winning over the type-wide ContentType.allowedChildTypes.

Empty in both means "any type allowed". The server enforces this on every tree-write; the new-entry dialog filters its dropdown to match.

Folders are content types

There is no special "folder" concept. The starter kit ships a Folder content type with isRoutable=false, isPublishable=false. Folders are entries of that type. The "New" context menu in the tree browser shows every type the parent permits — including Folder.

Tabs (uiConfig.tab)

Field-level. The CT editor exposes a Tab text input with autocomplete; values like "Content", "SEO", "Settings" group fields visually in the entry editor. Server treats tabs as opaque strings — only the editor reads them.

Tab order on the type comes from ContentType.uiConfig.tabOrder. Tabs not listed there fall to the end alphabetically.

availableSiteIds

When set, this list is stored and its IDs are existence-validated, but it is not enforced server-side at entry or tree creation today. Its current effect is in the UI: it filters the site choices in the new-entry dialog. Empty = available everywhere. Useful when a content type is genuinely tied to one site (e.g. a site-specific homepage block).

Example

{
"apiName": "blogPost",
"name": "Blog Post",
"isRoutable": true,
"isPublishable": true,
"parentApiName": "basePage",
"icon": "newspaper",
"uiConfig": { "tabOrder": ["Content", "SEO"] },
"fields": [
{
"apiName": "body",
"name": "Body",
"fieldType": "richtext",
"isRequired": true,
"isLocalizable": true,
"uiConfig": { "tab": "Content" }
},
{
"apiName": "publishedAt",
"name": "Published on",
"fieldType": "datetime",
"isFilterable": true,
"isSortable": true,
"uiConfig": { "tab": "Content" }
}
]
}

blogPost extends basePage, so it inherits title, slug, and the SEO fields automatically — no need to re-declare them.

Operations

  • krios types create --file blog-post.json — create
  • krios types list — list types in the configured project
  • krios types get <apiName> — read a single type with its full field list
  • krios types generate — emit TypeScript interfaces matching the project's schema