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.