Skip to main content

Field Types

Krios ships eleven built-in field types plus a custom-field-type registry for extension via iframe-rendered widgets.

Built-in types

TypeWhen to use
textOne-line strings, short paragraphs, slugs that don't need conflict checks. Optional validations.regex + patternName (Email, URL, Phone, Hex Color, Alphanumeric, Letters Only, Custom).
richtextLong-form authored content — paragraphs, headings, lists, embeds. Stored as a structured AST; renders to HTML at delivery.
numberIntegers / floats. Optional min / max.
booleanSingle checkbox.
datetimeISO 8601 timestamps. validations.dateOnly = true for pure dates.
mediaReference to a MediaAsset. validations.allowedAssets constrains kinds + extensions.
referencePointer to another entry. allowedTypeIds restricts which content types are valid.
enumPredefined option set. Field create requires a non-empty enumValues: string[] (omitting it → 422 enum_requires_values). validations.enumOptions: [{ key, label, description? }] is optional metadata that adds labels/descriptions. Multi-select is controlled by the field's isMultiple flag — the same flag reference / media use — not a separate enum-only toggle.
blocksOrdered list of embedded entries (page composition). Requires a non-empty allowedTypeIds (empty → 422 blocks_require_types) — unlike reference, it does not treat empty as "any type".
slugURL segment. The slug comes from the entry's slug (or is derived from the tree path at routing time), with a manual per-entry override.
linkCompound link with `mode: internal

Engineering notes

  • richtext stores a structured AST (close to ProseMirror's shape). Validation runs in lib/richtext/validate.ts and rejects documents that violate the field's richTextConfig. See Rich text.
  • media stores asset IDs (or arrays). The validator looks the IDs up to confirm they exist + match the kind/extension policy.
  • reference / blocks store entry IDs. The reference table (ContentReference) is bidirectional — used for "Where used" + reference-safe delete.
  • link is a compound JSON value with a mode discriminator. See lib/links/index.ts for the validator and effective config.
  • enum stores option keys. The required input is enumValues: string[] — the canonical option list; validations.enumOptions ([{ key, label, description? }]) is optional metadata for labels/descriptions and is not auto-synced with enumValues.
  • slug takes its value from the entry's slug, or derives it from the tree path (TreeNode.path) at routing time; either way a manual per-entry override wins. There is no validations.slugFromTreePath config key.

Custom field types

Custom field types render as an iframe in the entry editor and communicate via postMessage. The CMS persists the value as JSON; values are validated against a JSON Schema on every save.

# Register via the admin UI (Settings → Custom fields) or via REST:
curl -X POST -H "Authorization: Bearer $MK" -H "Content-Type: application/json" \
http://localhost:3000/api/v1/projects/demo/custom-field-types \
-d '{
"name": "Color picker",
"apiName": "colorPicker",
"hostedUrl": "https://my-widget.example.com",
"validationSchema": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$" }
}'

Once registered, colorPicker shows up in the field-type dropdown alongside the eleven built-ins. Storage uses the custom:colorPicker prefix so the field-definition table doesn't need a schema change. See @krios/custom-element-sdk for the widget side.

Per-field flags

FlagEffect
isRequiredPublish gate: required fields must have a value before the entry can be published.
isLocalizableOne value per locale (otherwise stored under __shared).
isMultipleField stores an array (applies to reference, media, enum).
isSearchableValue contributes to the entry's full-text search index.
isFilterableAdvisory in V1. Marks the field as intended for filtering; the GraphQL collection where input is generated but the resolver does not yet apply it. Full enforcement is V2.
isSortableAdvisory in V1. Marks the field as intended for sorting; collections currently sort by updatedAt (GraphQL) — REST sorts only createdAt / updatedAt. Full enforcement is V2.
isSensitiveMarks the field as PII. Redaction / export-exclusion is V2 behavior; in V1 it's advisory metadata.