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
| Flag | Effect |
|---|---|
isRoutable | Entry has a URL. Publishing writes a row to RouteIndex. |
isPublishable | Entry can be published / unpublished. Folders typically have this off. |
isSingleton | Reserved / 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— createkrios types list— list types in the configured projectkrios types get <apiName>— read a single type with its full field listkrios types generate— emit TypeScript interfaces matching the project's schema