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