Schema reference

Computed fields

Auto-derive a field's value from another field. Slug from title is the canonical case; transforms and modes cover the rest.

Not verified yet

A computed field's value is derived from another field rather than typed in by the author. The canonical case is slug from title — the author writes "Hello world" in the title, the slug field auto-fills to "hello-world", committed when they Publish. Other cases: lowercase a username, title-case a tag, reformat a date, trim trailing whitespace.

This page covers:

  • The computed shape — where the value comes from, how it's transformed, and how aggressively the auto-fill runs.
  • The four built-in transforms + the catch-all for custom ones.
  • The three modes (auto, once, suggest) and when to pick each.
  • How computed interacts with visibleIf and validation.

The shape

computed goes on the field that should be auto-filled, not the source.

- key: title
  type: text
  label: Title

- key: slug
  type: text
  label: Slug
  computed:
    from: title # path to the source field
    transform: slug # how to derive the value
    mode: auto # when to run the derivation
KeyEffect
fromPath to the source field. Same path syntax as visibleIf.field.
transformHow to convert the source value to the target value. See Transforms.
modeWhen the derivation runs. See Modes.

The path resolver is the same one visibleIf uses — sibling by default, $parent.key / $root.path.x / $item.flag for non-sibling sources.

Transforms

Each transform reads the source value and produces the derived value. The built-in registry covers the common cases; new transforms can register under custom names.

slug

The most common case. Lowercases, collapses runs of non-alphanumerics to a single hyphen, trims leading / trailing hyphens.

"Hello World"        → "hello-world"
"Article 42 / Part 2" → "article-42-part-2"
"  whitespace  "     → "whitespace"

Non-ASCII characters become hyphens (no transliteration table; matches the storage-side naming: slug strategy). All-symbol input produces an empty string — handle this in your field's default: if you need a fallback.

lowercase / titleCase

Case transforms — straightforward.

"Hello World" → "hello world"      (lowercase)
"hello world" → "Hello World"      (titleCase)

trim

Strip leading and trailing whitespace. Useful for fields where the source might come from a paste that includes incidental whitespace.

"  Hello  " → "Hello"

date:<format>

Reformat a date value. The format string is YYYY-MM-DD-style tokens.

- key: publishedAt
  type: date
  label: Published at

- key: yearMonth
  type: text
  label: Year-month
  computed:
    from: publishedAt
    transform: 'date:YYYY-MM'

Supported tokens: YYYY, YY, MM, M, DD, D, HH, mm, ss.

Custom

Schemas can register additional transforms by name. The transform: value is opaque to the schema validator — unknown transforms produce a severity: warning from the schema-warnings validator (so the author sees the typo).

Modes

mode: controls how aggressively the derivation overwrites the field.

ModeWhen the value updatesUse when
autoContinuously — every change to from overwrites the value.The derivation is the source of truth (slug, lowercase username).
onceOnly when the field is first created.Initial value seeding — author can then override.
suggestManual + a "Use derived value" affordance under the field.Suggestion-only — author always picks.

auto — continuous derivation

- key: slug
  type: text
  label: Slug
  computed:
    from: title
    transform: slug
    mode: auto

The field reads as read-only (greyed out) in the editor. Every keystroke in title updates slug live. Author can't override directly — they edit title instead.

Use auto when the derivation is the source of truth and a manual override would break invariants downstream (a URL slug that the deployed site routes on, a normalised username the auth system keys off).

once — seed and forget

- key: slug
  type: text
  label: Slug
  computed:
    from: title
    transform: slug
    mode: once

The field reads as a normal editable input. When the page is first created, the slug pre-fills from the title's transform. After that, the author owns the slug — changes to title no longer touch it.

Use once for initial seeding — the derivation is convenient but the author needs to be able to override later. CloudCannon calls this instance_value.

suggest — manual with a hint

- key: slug
  type: text
  label: Slug
  computed:
    from: title
    transform: slug
    mode: suggest

The field reads as a normal editable input. The editor shows a small "Use derived value" affordance under the field — clicking it copies the current derived value into the input. The author always picks.

Use suggest when the derivation is a hint, not an answer — the field is the author's domain, but a sensible default is one click away.

Path syntax for from

Same as visibleIf.field — see Conditional rendering → Path syntax for the full table.

Most computed fields use the sibling form (from: title), but absolute paths work too:

# In a nested block:
- key: prefixedTitle
  type: text
  label: Prefixed title
  computed:
    from: $root.site.titlePrefix # source on the page root
    transform: trim
    mode: once

Interaction with visibleIf

A computed field hidden by visibleIf doesn't run its derivation — there's no input to display, no behaviour to gate. When visibility flips back on, the derivation re-runs (for auto) or stays as-stored (for once / suggest).

whenHidden: drop purges the computed value on Publish when the field is hidden, matching the same rule for any field.

Interaction with validation

Computed values flow through the same validator pipeline as typed-in values:

  • A computed slug with regex: "^[a-z0-9-]+$" validates the derived value. The slug transform almost always satisfies the regex, but the check is still there.
  • A computed field with required: true fails when the source is empty.
  • Custom validators (customValidators) apply to computed values too.

The computed-vs-validation race is handled by running the computation synchronously inside validatePage — the validator sees the derived value, not a stale one. No $effect-ordering ambiguity.

When NOT to use computed

  • For values that depend on multiple fieldsfrom: takes one path. For a multi-source derivation, register a custom transform that reads from a known set of sibling paths.
  • For values the build pipeline should compute — when the value is trivially derivable at build time (a content-hash, a word-count, a reading-time estimate), prefer to keep it out of frontmatter entirely. computed is for values you want stored in frontmatter (because the build doesn't have access, or because the derivation is non-trivial).
  • For conditional defaultsdefault: covers static defaults; visibleIf + default covers per-condition defaults. computed is for derivations from a live source value.

Edge cases

Missing source

If from resolves to undefined, the transform receives undefined and returns its empty equivalent ("" for string transforms, 0 for numeric). For auto mode this means the computed field reads empty until the source has a value. For once / suggest it means the seed / suggestion is empty — the author can type in the actual value.

Source type mismatch

If from resolves to a value the transform doesn't expect (a number into slug, an object into trim), the transform best-effort-stringifies first. Result is whatever the transform produces from that string.

Editing the derived value (auto mode)

The editor's input is read-only. Authors can't type directly; the field is visually disabled. Future iterations might let auto allow override with a "break the link" affordance — not shipped today.

On this page