Docs
Tutorials
How-to guides
Reference
Explanation
Release notes
Search
Docs
/

Schema Field Types Reference

This reference documents all available field types for defining Schemas in Ligantic. Schemas define the structure of your data and are the foundation for both Experiences and Flows.

Field Type Overview

Field Type

Description

Supported Validations

string

Text values

required, minLength, maxLength, pattern, minWords, maxWords

number

Numeric values

required, min, max

boolean

True/false values

required, mustBeChecked, mustNotBeChecked

date

Date and datetime values

required

duration

Time duration values

required

recurrence

Recurring event/period rules (RRULE / RFC 5545)

required

file

File attachments

required, minLength, maxLength

content

Rich text content

required, minLength, maxLength, minBlocks, maxBlocks, minWords, maxWords

geojson

Geographic data

required

object

Nested object structure

required

array

List of values

required, minLength, maxLength

relationship

Link to other Records

required

Common Properties

All field types share these base properties:

Property

Type

Required

Default

Description

type

string

Yes

—

Field type identifier

name

string

Yes

—

Display name (min 1 character)

order

number | null

No

null

Sort order in UI

description

string | null

No

null

Help text for the field

required

boolean | null

No

null

Whether field is required

showInTable

boolean | null

No

true

Show in table views

string

Text values with optional display modes and validation.

Properties

Property

Type

Required

Default

Description

type

"string"

Yes

—

Field type identifier

display

"text" | "textarea" | "select" | "radio"

No

"text"

Input display mode

placeholder

string

No

—

Placeholder text

options

(string | { label: string, value: string })[]

No

—

Options for select display

default

string | null

No

null

Default value

validations

array

No

—

Validation rules

Display Modes

Mode

Description

Use Case

text

Single-line text input

Names, emails, short text

textarea

Multi-line text input

Descriptions, notes

select

Dropdown selection

Predefined choices

radio

Radio button group

Single choice selection

select options support two formats:

  • "Option" (label and value are both "Option")
  • { "label": "Option Label", "value": "option-value" }

Supported Validations

  • required — Field must have a value
  • minLength — Minimum character count
  • maxLength — Maximum character count
  • pattern — Regex pattern match
  • minWords — Minimum word count
  • maxWords — Maximum word count

Example

{
  "type": "string",
  "name": "Email Address",
  "display": "text",
  "placeholder": "Enter your email",
  "validations": [
    {
      "rules": [
        { "type": "required", "message": "Email is required" },
        {
          "type": "pattern",
          "value": "^[^@]+@[^@]+\\.[^@]+$",
          "message": "Invalid email format"
        }
      ]
    }
  ]
}

number

Numeric values (integers or decimals), with a configurable display format.

Properties

Property

Type

Required

Default

Description

type

"number"

Yes

—

Field type identifier

default

number | null

No

null

Default value

defaultFormat

object

No

—

Default display format for this field (see below)

validations

array

No

—

Validation rules

Number Format

The defaultFormat property controls how number values are displayed. It changes only the display; the stored value stays a plain number. It uses a discriminated union:

Type

Properties

Description

"preset"

preset: string

One of the built-in format presets (see below)

"custom"

style, currency, minimumFractionDigits, maximumFractionDigits, useGrouping

Custom options (see below)

Formatting follows the viewer's locale, so separators differ by locale (for example, 1,234.50 in en-AU and 1.234,50 in de-DE).

Format Presets

Preset

Example Input

Example Output

Notes

"integer"

1234.5678

1,235

Rounded to a whole number

"decimal"

1234.5678

1,234.57

Exactly two decimal places

"percent"

0.256

25.6%

Value is a fraction: 1 is 100%

"compact"

1234567

1.2M

Short scale notation

"scientific"

1234.5678

1.235E3

Scientific notation

Custom Options

Property

Type

Required

Description

style

"decimal" | "percent" | "currency"

Yes

Plain number, percent (value is a fraction), or currency

currency

string

When style is "currency"

Three-letter ISO 4217 code in upper case, such as "AUD"

minimumFractionDigits

integer (0–20)

No

Fewest decimal places to show, padding with zeros

maximumFractionDigits

integer (0–20)

No

Most decimal places to show, rounding the rest

useGrouping

boolean

No

Show thousands separators. Defaults to true

Example: { "type": "custom", "style": "currency", "currency": "AUD" } → $1,234.50

If the options cannot be applied (for example, "currency" style without a currency, or minimumFractionDigits greater than maximumFractionDigits), the number is shown unformatted.

Format Cascade

When displaying a number value, formats are resolved in this order:

  1. Variable-level format — format specified on the variable reference in a content template
  2. Field-level defaultFormat — the Schema field's configured default format
  3. Unformatted — the number as stored, such as 1234.5

Supported Validations

  • required — Field must have a value
  • min — Minimum value (inclusive)
  • max — Maximum value (inclusive)

Example

{
  "type": "number",
  "name": "Age",
  "default": 18,
  "defaultFormat": {
    "type": "preset",
    "preset": "integer"
  },
  "validations": [
    {
      "rules": [
        { "type": "required" },
        { "type": "min", "value": 0, "message": "Age must be positive" },
        { "type": "max", "value": 150, "message": "Invalid age" }
      ]
    }
  ]
}

Expression Input

In the editor, a number field also accepts arithmetic expressions. Prefix the value with = to evaluate it on blur or Enter, for example, =2 + 3 * 4 commits 14.

  • Operators: +, -, *, /, and x/X for multiplication; parentheses for grouping; unary +/- for signs.
  • Scientific notation is supported, for example, =1.5e-2 commits 0.015.
  • A trailing % divides the number by 100. In additive contexts the percent is relative to the other operand: =100 + 10% commits 110 and =100 - 10% commits 90. In multiplicative contexts it is an absolute fraction: =100 * 10% commits 10.
  • An invalid expression reverts the field to its last committed value on blur or Enter.
  • Pressing Enter on an expression evaluates it without submitting the form; pressing Enter on a plain number commits it and submits the form normally.

boolean

True/false toggle values.

Properties

Property

Type

Required

Default

Description

type

"boolean"

Yes

—

Field type identifier

default

boolean | null

No

null

Default value

validations

array

No

—

Validation rules

Supported Validations

  • required — Field must have a value (true or false, not null)
  • mustBeChecked — Field must be true; intended for consent or terms-and-conditions style checkboxes
  • mustNotBeChecked — Field must be false; intended for flows where a checkbox must remain unchecked

Validation Semantics

  • required only enforces that the stored value is not null or undefined. Both true and false satisfy this rule.
  • mustBeChecked enforces an explicit true value. false, null, and undefined fail validation.
  • mustNotBeChecked enforces an explicit false value. true, null, and undefined fail validation.
  • Use mustBeChecked for opt-in consent flows. Leave the field without validations when the checkbox is optional.
  • Use mustNotBeChecked when the unchecked state is the valid submission requirement.

Example

{
  "type": "boolean",
  "name": "Accept Terms",
  "default": false,
  "validations": [
    {
      "rules": [{ "type": "mustBeChecked", "message": "You must accept the terms" }]
    }
  ]
}

date

Date and datetime values. Supports per-value timezone storage via IANA timezone identifiers (for example, 2024-05-15T23:20:16+10:00[Australia/Melbourne]), configurable display formats, and timezone display preferences.

When a datetime includes both an offset and an IANA timezone annotation, the annotated timezone is treated as authoritative for wall-clock scheduling. If they conflict, the value is normalised by preserving the provided wall time in the annotated timezone (the offset is adjusted to match the zone).

Properties

Property

Type

Required

Default

Description

type

"date"

Yes

—

Field type identifier

includeTime

boolean

No

false

Include time component

default

string | "now" | "today" | null

No

null

Default value or special value

defaultFormat

object

No

—

Default display format for this field (see below)

timezoneDisplay

"source" | "viewer"

No

—

Show dates in the stored (source) or viewer's timezone

validations

array

No

—

Validation rules

Date Format

The defaultFormat property controls how date values are displayed. It uses a discriminated union:

Type

Properties

Description

"preset"

preset: string

One of the built-in format presets (see below)

"custom"

pattern: string

A custom CLDR/Unicode date format pattern

Format Presets

Preset

Example Output

Notes

"short"

1/15/24

Date only

"medium"

Jan 15, 2024

Date only

"long"

January 15, 2024

Date only

"full"

Monday, January 15, 2024

Date only

"shortDateTime"

1/15/24, 2:30 PM

Requires includeTime: true

"mediumDateTime"

Jan 15, 2024, 2:30 PM

Requires includeTime: true

"longDateTime"

January 15, 2024 at 2:30:00 PM EST

With timezone name

"fullDateTime"

Monday, January 15, 2024 at 2:30:00 PM Eastern Standard Time

Full date + time + timezone

"timeOnly"

2:30 PM

Time only, requires includeTime

Custom Pattern

Uses CLDR/Unicode date format tokens. When timezoneDisplay resolves a timezone ("source" or "viewer"), custom patterns are rendered in that timezone. If no display timezone can be resolved, formatting falls back to the runtime local timezone. Common tokens:

  • yyyy — 4-digit year, MM — 2-digit month, dd — 2-digit day
  • HH — 24-hour, hh — 12-hour, mm — minutes, ss — seconds
  • a — AM/PM, EEEE — full weekday name, MMMM — full month name

Example: "dd/MM/yyyy HH:mm" → 15/01/2024 14:30

Timezone Display

When includeTime is true, the timezoneDisplay property controls which timezone is used for rendering:

  • "source" (default): Display in the timezone stored with the value
  • "viewer": Convert to the viewer's timezone (from user preferences or browser)

Format Cascade

When displaying a date value, formats are resolved in this order:

  1. Variable-level format — format specified on the variable reference in a content template
  2. Field-level defaultFormat — the Schema field's configured default format
  3. ISO fallback — raw ISO string if no format is configured

Default Values

Value

Description

"now"

Current date and time

"today"

Current date at midnight

ISO string

Specific date/time value

"today" uses the calendar date in the viewer's timezone when one is available (for example, Flows that create Records use the triggering user's timezone). Otherwise it uses the runtime's timezone, which is the browser timezone in forms. Date-only fields get a plain date such as 2026-04-08. Fields with includeTime: true get midnight in that timezone with its IANA identifier, such as 2026-04-08T00:00:00+10:00[Australia/Brisbane].

In an Experience, "now" and "today" read the time the page was loaded until the page has finished loading its data. Blocks that appear after that read the time they appear.

Supported Validations

  • required — Field must have a value

Example

{
  "type": "date",
  "name": "Event Date",
  "includeTime": true,
  "default": "now",
  "defaultFormat": {
    "type": "preset",
    "preset": "longDateTime"
  },
  "timezoneDisplay": "viewer",
  "validations": [
    {
      "rules": [{ "type": "required" }]
    }
  ]
}

duration

Time duration values (ISO 8601 duration format).

Properties

Property

Type

Required

Default

Description

type

"duration"

Yes

—

Field type identifier

validations

array

No

—

Validation rules

Supported Validations

  • required — Field must have a value. A zero duration (PT0S) counts as a value and satisfies required.

Duration supports no other constraints: there is no minimum, maximum, allowed-unit or precision option.

Duration Format

Durations use ISO 8601 designator format: P[n]Y[n]M[n]W[n]DT[n]H[n]M[n]S

Examples:

  • PT1H — 1 hour
  • PT30M — 30 minutes
  • P1D — 1 day
  • P1W — 1 week
  • P1Y2M3D — 1 year, 2 months, 3 days
  • -PT1H30M — negative 1 hour 30 minutes
  • PT0.5S — half a second

What is accepted:

Zero

Yes — PT0S

Negatives

Yes, with a leading - on the whole value

Weeks

Yes

Fractional values

Yes, on the smallest unit present, down to nanosecond precision

Mixed signs

No — P1M-1D is rejected

Only ISO 8601 is accepted. Values such as "90 minutes", "1:30" and a bare number are rejected. The API, CSV import, the editor, and AI-driven Flows accept exactly the same set of values.

Entry and Display

Durations are entered through a segmented control with a field per unit — years, months, weeks, days, hours, minutes, seconds — plus a sign toggle that appears when the value is negative or when you engage the control. Negative durations are legal.

Values are stored exactly as authored and are never normalised. A duration entered as PT90M stays PT90M; it is shown as 90 minutes in the control and displayed as 90m, not 1h 30m.

Tab moves directly between unit inputs, skipping the stepper buttons. Up and Down arrow keys adjust the focused unit; the stepper buttons remain clickable.

Stepping a field with the arrow keys carries into the next unit — 60s to 1m, 60m to 1h, 24h to 1d, 30d to 1mo, 12mo to 1y. Typing a value directly is never rewritten: type 31 into days and the value stays 31 days.

Display uses compact unit notation, largest unit first, with zero components omitted: 1y 2mo 3d 4h 5m 6s. Negatives take a leading minus (-1h 30m). A zero duration displays as 0s; an unset field displays as empty.

Sorting and Filtering

Durations sort and compare by elapsed time, not by the text of the stored value. Calendar units have no fixed length, so comparison uses a fixed conversion: one month counts as 30 days, and one day counts as 24 hours.

Consequences worth knowing:

  • P1M, P30D and PT720H all compare as equal.
  • P1Y counts as 360 days, so P1Y is less than P365D.
  • eq matches on elapsed time, so filtering a field for P1M also returns Records storing P30D.

Equality follows the same rule as ordering, so filtering for eq P1M returns the same Records as gte P1M AND lte P1M.

Records that tie on elapsed time fall back to the stored text for a stable, repeatable order.

The comparison operators eq, ne, gt, gte, lt, lte, in and nin all use this rule. isNull and isNotNull test only for the presence of a value.

Import, Export and AI

CSV export writes the bare ISO 8601 string as stored (P1M, not 1mo), and CSV import accepts the same, so a round trip is lossless. An empty cell imports as unset; an unparseable one is reported as an invalid file rather than being silently guessed at.

In generated JSON Schema — including the tool schemas handed to AI models — a duration field is emitted as a string with format: "duration" and a matching pattern.

Example

{
  "type": "duration",
  "name": "Meeting Length",
  "validations": [
    {
      "rules": [{ "type": "required" }]
    }
  ]
}

recurrence

A recurring event or period, grounded in RRULE / RFC 5545. A recurrence is a rule + a DTSTART anchor + an optional extent (duration). With no extent it is a point event ("deliver every Monday"); with an extent it is a period ("a delivery window each Monday, 09:00–12:00"). This is the RFC 5545 model: a period is an event with a DURATION.

Every occurrence is a zoned date-time, and wall-clock time is preserved across DST — a rule anchored at 09:00[America/Chicago] fires at 09:00 local wall time on every occurrence, including across a spring-forward. The full RFC 5545 grammar is supported, including BYSETPOS ("the 2nd / last Friday").

Properties

Property

Type

Required

Default

Description

type

"recurrence"

Yes

—

Field type identifier

includeTime

boolean

No

false

Anchor carries a time component. When false or omitted (all-day), the anchor must be at midnight, and the editor does not set a time of day

validations

ValidationGroup[]

No

—

Validation rules

Supported Validations

  • required — Field must have a value

Value shape

The stored value is a structured, JSON-safe object holding the RFC 5545 recurrence parts, a ZonedDateTime ISO anchor, and an optional ISO-8601 duration extent (reusing the duration representation):

Field

Type

Description

dtstart

ZonedDateTime ISO string

The anchor. Carries an IANA zone annotation. Omitted for a rule with no start date; see Rules without a start date

tzid

IANA time zone name

The time zone of a rule with no start date, written exactly as named in the IANA database, e.g. Australia/Melbourne. UTC offsets such as +10:00 are not accepted. Not allowed together with dtstart, which carries its own zone

freq

YEARLY…SECONDLY

Recurrence frequency (required)

interval

number (≥ 1)

Every n-th freq unit

count

number (≥ 1)

Stop after n occurrences. Mutually exclusive with until (RFC 5545)

until

UTC ZonedDateTime ISO string

Stop after this instant. Must be UTC when the anchor carries a zone (RFC 5545)

byDay

string[]

Weekday tokens: MO, 2FR, -1SU (ordinal + weekday). An ordinal is 1 to 53 or -53 to -1

byMonth

number[] (1–12)

Restrict to these months

byMonthDay

number[] (−31…31, ≠ 0)

Restrict to these days of month (negative = from end)

byYearDay

number[] (−366…366, ≠ 0)

Restrict to these days of year

byWeekNo

number[] (−53…53, ≠ 0)

Restrict to these week numbers

bySetPos

number[] (−366…366, ≠ 0)

Select the n-th / last item after the other BY* filters

byHour

number[] (0–23)

Restrict to these hours

byMinute

number[] (0–59)

Restrict to these minutes

bySecond

number[] (0–60)

Restrict to these seconds (60 = leap second)

wkst

MO…SU

Week start day (default MO)

exdate

ZonedDateTime ISO string[]

Explicitly excluded occurrences

rdate

ZonedDateTime ISO string[]

Additional (one-off) occurrences

duration

ISO 8601 duration

The extent — makes the recurrence a period rather than a point

The RFC 5545 RRULE string is a derived interop form of this value, not the canonical storage. In a Flow, the recurrenceToRRule expression function produces the DTSTART;TZID=… + RRULE lines. The lines do not include the extent: for a period, add duration as a DURATION property where you need it. For a rule without a start date, DTSTART is its first occurrence on or after 1 January 1970 in its time zone; a rule with no occurrences fails with "The recurrence rule has no occurrences to export". RSCALE/SKIP parts (RFC 7529) are not supported.

Rules without a start date

A recurrence can omit dtstart and still carry a time of day, for example "weekly on Tuesday at 8:54 PM". The editor stores such a rule with the author's time zone in tzid and the time in byHour/byMinute:

{
  "freq": "WEEKLY",
  "byDay": ["TU"],
  "byHour": [20],
  "byMinute": [54],
  "tzid": "Australia/Melbourne"
}
  • Occurrences fall at exactly the byHour/byMinute/bySecond time in tzid (midnight when there is none), wherever and whenever the rule is expanded.
  • A rule without tzid (saved before time zones were stored) is expanded in UTC. Open and save it in the editor to record your time zone.
  • interval counts from a fixed point in the past, so "every 2 weeks" falls on the same weeks every time it is expanded. Set a start date to choose which weeks.
  • To list its occurrences, a rule without a start date must say which days it falls on, and cannot have a count:

    freq

    Needs

    WEEKLY

    byDay

    MONTHLY

    byMonthDay or byDay

    YEARLY

    byMonthDay, byDay, or byYearDay; with byWeekNo, also byDay

    The editor shows a message such as "A yearly recurrence needs a start date" when a choice needs one. A stored value that does not meet these requirements still loads and shows its summary, and the editor shows the same message when it is opened; Flows that list its occurrences fail with that message until a start date or the missing days are added.

Example

{
  "type": "recurrence",
  "name": "Delivery Schedule",
  "includeTime": true,
  "validations": [{ "rules": [{ "type": "required" }] }]
}

A value for that field — "every Monday at 09:00 America/Chicago, for a 3-hour window, up to 10 times":

{
  "dtstart": "2024-01-01T09:00:00-06:00[America/Chicago]",
  "freq": "WEEKLY",
  "byDay": ["MO"],
  "count": 10,
  "duration": "PT3H"
}

Authoring

Recurrence fields are created in the designer like any other field type. The value editor is a curated picker over the full grammar, so the common cases are a few clicks while the stored value remains the full RFC 5545 structure. It sets:

  • Starts and Time: the anchor. Clear the start date for a rule with no start date.
  • Time zone: the zone the rule happens in. The current zone is shown in a collapsed row; expanding it reveals the selector. A new rule takes your time zone. An existing rule with neither a start date nor an explicit time zone uses UTC. Changing the time zone keeps the same wall-clock time in the new zone.
  • Frequency and Every: freq and interval, daily to yearly.
  • On: which days the rule falls on:

    • Weekly: one or more weekdays.
    • Monthly: one or more days of the month, including Last day (byMonthDay: [-1]), or the Nth / last weekday ("the 2nd Friday"). Months too short for a chosen day skip it, so use Last day for the end of every month.
    • Yearly: the start date's day each year, or the Nth / last weekday of a month ("the 4th Thursday of November").
  • Skip dates: dates with no occurrence, stored in exdate. Each skipped date removes every occurrence that day, and follows the rule if you later change its time or time zone. Both the summary and the date list show skipped dates in the recurrence's time zone. Up to three dates are shown in chronological order: the most recent past skip, the next upcoming skip (including today), and the closest remaining date to today in the rule's time zone. Equal distances favour the upcoming date; if all skips are on one side of today, the nearest three are shown. Additional dates are in an expandable disclosure. Skip adds a date without closing the editor and returns focus to the date input.
  • Duration: the extent, which makes the recurrence a period ("weekly on Monday at 9:00 AM for 3h"). The duration must be longer than zero.
  • End: never, after a number of occurrences (count), or on a date (until).

When the field is disabled, its value cannot be changed or cleared, even if the picker is already open.

Parts of a stored value the editor has no control for (rdate, bySecond, wkst, several times a day, minute-only constraints without an hour, and byHour/byMinute alongside a start date) are kept unchanged when the value is edited. Entering an explicit time replaces minute-only constraints with that time. The same goes for a day selection the editor cannot show, such as byYearDay or byWeekNo: the editor says so and keeps it until you choose Replace day pattern or change the frequency.

Using recurrences in Flows

Use the Data - Recurrence node to list the occurrences in a date range, find the next or previous occurrence, or test whether a date/time falls on one. The same operations are available as expression functions. A Flow trigger can also take a recurrence as an input.

file

File attachments with type restrictions.

Properties

Property

Type

Required

Default

Description

type

"file"

Yes

—

Field type identifier

multiple

boolean

No

false

Allow multiple files

displayMediaPreview

boolean

No

false

Show media and document previews

allowedTypes

array

Yes

—

Allowed file type categories

maxSize

number

No

5242880

Max file size in bytes (5MB default)

validations

array

No

—

Validation rules

File Type Categories

Category

Extensions

image

jpg, jpeg, png, gif, webp, svg

video

mp4, webm, mov, avi

audio

mp3, wav, ogg, m4a

document

pdf, doc, docx, txt, rtf

spreadsheet

xls, xlsx, csv

presentation

ppt, pptx

archive

zip, rar, 7z, tar, gz

code

js, ts, py, java, html, css, json

Supported Validations

  • required — At least one file must be uploaded
  • minLength — Minimum number of uploaded files when multiple: true
  • maxLength — Maximum number of uploaded files when multiple: true

Validation Semantics

  • required ensures the field is not empty.
  • minLength and maxLength count the number of uploaded files, not the length of file names.
  • Count validations are only intended for file fields with multiple: true.
  • When a maxLength validation group has an activation rule, the editor only disables additional uploads while that activation rule matches the current form values.
  • maxSize continues to apply to each file individually.
  • Once maxLength is reached, the UI normally blocks further uploads; in rare cases, more files can still be uploaded.

Preview

When displayMediaPreview is true, supported images, video, audio, DOCX, PDF, and PPTX files are rendered inline. DOCX and PDF files are displayed as paginated document previews; PPTX files are displayed as a scrollable slide preview. In Record tables, document files remain filename links instead of rendering inline; a preview button opens the full document in a modal. The same button appears in the top-left of an inline document preview. PDFs remain file links when the browser does not support canvas rendering. Other file types remain file links with a download action.

Example

{
  "type": "file",
  "name": "Profile Photo",
  "multiple": true,
  "displayMediaPreview": true,
  "allowedTypes": ["image"],
  "maxSize": 10485760,
  "validations": [
    {
      "rules": [
        { "type": "required", "message": "Please upload supporting files" },
        { "type": "minLength", "value": 2, "message": "Upload at least two files" },
        { "type": "maxLength", "value": 5, "message": "Upload no more than five files" }
      ]
    }
  ]
}

content

Rich text content, stored as an array of blocks.

Properties

Property

Type

Required

Default

Description

type

"content"

Yes

—

Field type identifier

allowedBlocks

array

No

See Block Types

Allowed block types

allowedMarks

array

No

See Mark Types

Allowed mark types

placeholder

string

No

—

Placeholder text

hoveringToolbar

boolean

No

true

Show floating toolbar on selection

validations

array

No

—

Validation rules

Block Types

When allowedBlocks is omitted, the field allows the blocks in this table. Other block types can only be used when listed in allowedBlocks.

Block

Description

paragraph

Standard paragraph

heading1 to heading6

Heading levels

block-quote

Block quote

numbered-list

Numbered list

bulleted-list

Bulleted list

list-item

List item

code

Code block

link

Hyperlink

image

Embedded image

video

Embedded video

audio

Embedded audio

table

Table

Mark Types

When allowedMarks is omitted, the field allows the marks in this table. Other marks can only be used when listed in allowedMarks.

Mark

Description

bold

Bold text

italic

Italic text

underline

Underlined text

deleted

Strikethrough text

code

Inline code

Writing Content Values

When creating, patching, JSON-patching, or replacing a Record through the API, a content field's value can be either the block array or a plain markdown string. A markdown string is converted to blocks, so the stored value is always a block array. This applies at any depth inside object and array fields.

Supported Validations

  • required — Content must not be empty
  • minLength — Minimum character count
  • maxLength — Maximum character count
  • minBlocks — Minimum block count
  • maxBlocks — Maximum block count
  • minWords — Minimum word count
  • maxWords — Maximum word count

Example

{
  "type": "content",
  "name": "Article Body",
  "allowedBlocks": [
    "paragraph",
    "heading1",
    "heading2",
    "block-quote",
    "numbered-list",
    "bulleted-list",
    "image"
  ],
  "allowedMarks": ["bold", "italic", "code"],
  "placeholder": "Write your article here...",
  "hoveringToolbar": true,
  "validations": [
    {
      "rules": [
        { "type": "required" },
        {
          "type": "minWords",
          "value": 100,
          "message": "Article must be at least 100 words"
        }
      ]
    }
  ]
}

geojson

Geographic data stored either as raw GeoJSON or, in map editors, as standard geography references.

Properties

Property

Type

Required

Default

Description

type

"geojson"

Yes

—

Field type identifier

geometryTypes

array

No

All types

Allowed geometry types

propertySchemaConfig

object

No

—

Schema for feature properties

display

object

No

{ display: "inputs" }

Display configuration

validations

array

No

—

Validation rules

Geometry Types

Type

Description

Point

Single coordinate

LineString

Line of coordinates

Polygon

Closed polygon

MultiPoint

Multiple points

MultiLineString

Multiple lines

MultiPolygon

Multiple polygons

Display Configurations

Inputs Display:

{
  "display": "inputs"
}

Map Display:

{
  "display": "map",
  "defaultZoom": 13,
  "defaultCenter": {
    "latitude": 40.7128,
    "longitude": -74.006
  }
}

Supported Validations

  • required — GeoJSON data must be provided

Example

{
  "type": "geojson",
  "name": "Store Location",
  "geometryTypes": ["Point"],
  "display": {
    "display": "map",
    "defaultZoom": 15,
    "defaultCenter": {
      "latitude": 51.5074,
      "longitude": -0.1278
    }
  },
  "validations": [
    {
      "rules": [{ "type": "required" }]
    }
  ]
}

When the map editor is used in geography-reference mode, values are stored as:

{
  "mode": "geography-reference",
  "rows": [
    {
      "id": "AU",
      "label": "Australia",
      "sources": [
        {
          "type": "reference",
          "geographySet": "world-country-ne-v1",
          "geographyCode": "AU"
        }
      ],
      "properties": {
        "displayCount": 10,
        "detailLevel": "Continental"
      }
    }
  ]
}

Row-level property data can be supplied either as additional top-level row keys or inside rows[].properties. Both are merged into the rendered feature's GeoJSON properties object. When using the map editor in geography-reference mode, clicking a selected geography keeps the current viewport and exposes inline label editors for the selected rows.

When shaping geography-reference values, you must choose the correct rows[].sources[].geographySet from the identifier level of your data (for example, country codes vs. subdivision codes). For detailed instructions on data shaping and a complete list of available geography sets, see Visualisation — Geography-Reference Data Shaping.

For one row to one shipped geography unit, the minimal reference-source shape is:

{
  "id": "US-CA",
  "sources": [
    {
      "type": "reference",
      "geographySet": "world-admin1-north-america-ne-v1",
      "geographyCode": "US-CA"
    }
  ]
}

object

Nested object with its own schema structure.

Properties

Property

Type

Required

Default

Description

type

"object"

Yes

—

Field type identifier

properties

object

Yes

—

Nested field definitions

validations

array

No

—

Validation rules

Supported Validations

  • required — Object must have values

Default Evaluation Order

When an object field contains conditional required rules, Ligantic evaluates property defaults in dependency order. If a property's required condition references another property, the referenced property's default is applied first, including when that dependency is introduced by nested object fields.

Example

{
  "type": "object",
  "name": "Address",
  "showInTable": false,
  "properties": {
    "street": {
      "type": "string",
      "name": "Street",
      "display": "text"
    },
    "city": {
      "type": "string",
      "name": "City",
      "display": "text"
    },
    "country": {
      "type": "string",
      "name": "Country",
      "display": "select",
      "options": ["United States", "United Kingdom", "Canada", "Australia"]
    },
    "postalCode": {
      "type": "string",
      "name": "Postal Code",
      "display": "text"
    }
  }
}

array

List of values with a defined item schema.

Properties

Property

Type

Required

Default

Description

type

"array"

Yes

—

Field type identifier

display

"form" | "table" | "checkboxes" | null

No

null

Array input display mode

items

object

Yes

—

Schema for array items

validations

array

No

—

Validation rules

Note: In Studio, selecting array display = "checkboxes" auto-configures items to a string select schema and shows the options editor at the array level (the nested item schema editor is hidden in this mode). If items is not a string schema, Studio shows a warning confirmation before applying this conversion.

Note: In Studio, array validation rule selection supports required, minLength, and maxLength, including when display = "checkboxes". Use minLength to require multiple checkbox selections.

Supported Validations

  • required — Array value must be present (can be empty)
  • minLength — Minimum item count
  • maxLength — Maximum item count

Example

{
  "type": "array",
  "name": "Tags",
  "items": {
    "type": "string",
    "name": "Tag",
    "display": "text"
  },
  "validations": [
    {
      "rules": [
        {
          "type": "minLength",
          "value": 1,
          "message": "At least one tag required"
        },
        {
          "type": "maxLength",
          "value": 10,
          "message": "Maximum 10 tags allowed"
        }
      ]
    }
  ]
}

Array of Objects Example

{
  "type": "array",
  "name": "Team Members",
  "items": {
    "type": "object",
    "name": "Member",
    "properties": {
      "name": {
        "type": "string",
        "name": "Name",
        "display": "text"
      },
      "role": {
        "type": "string",
        "name": "Role",
        "display": "select",
        "options": [
          { "label": "Developer", "value": "developer" },
          { "label": "Designer", "value": "designer" },
          { "label": "Manager", "value": "manager" }
        ]
      },
      "email": {
        "type": "string",
        "name": "Email",
        "display": "text"
      }
    }
  }
}

Validation Groups

Validations are organised into groups. Each group has:

  • condition (optional): when to apply these rules.
  • rules: the rules to apply.

Conditional Validation Example

{
  "type": "string",
  "name": "Company Name",
  "validations": [
    {
      "condition": {
        "type": "property",
        "path": ["isBusinessAccount"],
        "operator": "eq",
        "value": { "type": "literal", "value": true }
      },
      "rules": [
        {
          "type": "required",
          "message": "Company name required for business accounts"
        }
      ]
    }
  ]
}

Paths Relative to the Field

A condition path normally starts at the Record's top-level fields. A path that starts with @ starts at the field the rule belongs to instead:

  • @ is the field's own value.
  • Each ^ after it moves one level up. Every level counts, including an array: from a field at lines[2].hours, @^ is the line lines[2], @^^ is the lines array and @^^^ is the Record.
  • The segments after that go down from the level reached: @^.kind is lines[2].kind.

In JSON, write each part as its own segment, ["@", "^", "kind"]; the string forms "@.^.kind" and "@^.kind" are the same path.

For example, a hours field inside invoice lines can be required only on lines whose kind is service:

{
  "type": "number",
  "name": "Hours",
  "validations": [
    {
      "condition": {
        "type": "property",
        "path": ["@", "^", "kind"],
        "operator": "eq",
        "value": { "type": "literal", "value": "service" }
      },
      "rules": [{ "type": "required" }]
    }
  ]
}
  • Each line is checked against its own kind: the rule applies to the second line of [{ "kind": "goods" }, { "kind": "service" }] only.
  • In nested arrays, ^ keeps counting levels: from a field inside weeks[1].days[3], @^^^.billable is weeks[1].billable.
  • A path that goes above the Record, or has ^ after a field name, is invalid for that field: the condition never applies, including when it is negated with not.
  • In the Schema editor, a field's Apply when condition lists the field and each level above it with its relative path, e.g. Hours (@), Line (@^).Kind and Lines (@^^), before the Record's top-level fields.

relationship

Links a Record to one or more Records in another Schema. The field's value is the linked Record ID or IDs.

Properties

Property

Type

Required

Default

Description

type

"relationship"

Yes

—

Field type identifier

targetSchemaId

string (CUID2)

Yes

—

The Schema ID of the related Records

cardinality

"one" | "many"

Yes

—

Whether the field holds one or many references

targetLabel

string

No

Source Schema name

Label shown on the target Record's relationship side

displayTemplate

array

No

—

Template for rendering related Record labels

Behaviour

  • Cardinality "one": The field value is a single Record ID string (or null if empty).
  • Cardinality "many": The field value is an array of Record ID strings.
  • Target-side label default: The default is the source Schema name, pluralized when the target side has many-cardinality. On save, targetLabel is trimmed; omitted, empty, whitespace-only, or default-equivalent values are omitted so the cardinality-aware default applies.
  • Clearing the target-side label: Submitting an empty or default-equivalent targetLabel for a field that sends the property is an explicit revert — the relationship's label is reset to the cardinality-aware default, discarding any custom label previously set from the field or the relationship editor. A field that omits targetLabel entirely leaves the existing label untouched.
  • Target-side rendering: Record detail relationship sections and relationship table columns use the custom target-side label when present, otherwise they use the cardinality-aware default.
  • Adding and editing links in Studio: On a saved Record's page, a many-cardinality relationship field shows a + button in both its list and table display. It opens a lookup of the related Schema's Records with Link and Cancel: choose a Record and select Link (or press Enter) to link it. To link a new Record instead, select the + inside the lookup, or Add when a search finds nothing. This opens the related Schema's create form, with Cancel and Save and link kept at the top while the form scrolls; Save and link creates the Record and links it. The lookup and form open next to the field, or full screen on small screens. In the list display, each linked Record has Edit, which replaces it with a lookup to link a different Record, and Unlink; the table display has an unlink action on each row. These actions are not shown when the field is read-only, or when either side of the relationship is a field inside an array. The Relationships section of the Record page works the same way.
  • Querying: Relationship fields support property filters with operators eq, ne, in, isNull, and isNotNull.

Relationship Sides

A relationship field can be declared on either side of the relationship. The direction of the relationship does not depend on which Schema declares the field.

Saving the Schema updates only the target-side label, from targetLabel. It does not change the relationship's direction or the label and settings on the other side.

The Schema editor shows the target-side label currently in use, including changes made in the relationship editor.

Conversion Between Standalone and Field Forms

  • Converting a standalone relationship to a field adds a relationship field to the chosen Schema and keeps its direction, names, and cardinality.
  • Converting a field to a standalone relationship keeps its existing links and direction.
  • Changing a relationship field's targetSchemaId replaces the relationship with a new one. Links to the old target are not carried over.

Validations

Validation

Type

Description

required

boolean

Record must have at least one link

Page not found. It may have moved or may not be published.
Browse documentation