Layout, binding and help
These tokens shape where fields sit, how their values land in the resolver payload, and what guidance appears beside the form.
| Token | Placement | Purpose |
|---|---|---|
x-lt-layout |
Schema root | "two-column" arranges fields in a two-column grid |
x-lt-span |
Field | 2 spans the full width in a two-column layout |
x-lt-order |
Schema root | Explicit field order |
x-lt-section |
Field | Groups fields under a labeled section |
x-lt-column-group |
Field | Pairs consecutive fields inside one grid cell |
x-lt-bind |
Field | The path the field’s value occupies in the payload |
x-lt-help |
Schema root | Markdown guidance in the side panel |
x-lt-context |
Schema root | Plain-text guidance, the fallback when x-lt-help is absent |
Two-column layout (x-lt-layout)
Section titled “Two-column layout (x-lt-layout)”Set "x-lt-layout": "two-column" at the schema root to arrange fields in a two-column grid. Add "x-lt-span": 2 to a field to span the full width.
{ "x-lt-layout": "two-column", "properties": { "first_name": { "type": "string" }, "last_name": { "type": "string" }, "notes": { "type": "string", "format": "textarea", "x-lt-span": 2 } }}Field order (x-lt-order)
Section titled “Field order (x-lt-order)”Fields render in JSON key order unless x-lt-order sets a sequence. Fields missing from x-lt-order render after the listed ones, in their original key order.
{ "x-lt-order": ["priority", "decision", "notes"], "properties": { "notes": { "type": "string" }, "decision": { "type": "string", "enum": ["approve", "reject", "defer"] }, "priority": { "type": "number" } }}Sections (x-lt-section)
Section titled “Sections (x-lt-section)”Add "x-lt-section": "Label" to each property in a group. Consecutive fields that share a section name collect into one group with a header.
Sections follow the first field that carries the name (and so respect x-lt-order). A field without x-lt-section belongs to an unnamed group with no header. Named sections render with a left accent line, a small icon, and the label in uppercase.
{ "x-lt-layout": "two-column", "x-lt-order": ["orderId", "sku", "rush", "approved", "notes"], "properties": { "orderId": { "type": "string", "readOnly": true, "x-lt-section": "Facts", "x-lt-hide-if-empty": true }, "sku": { "type": "string", "readOnly": true, "x-lt-section": "Facts", "x-lt-hide-if-empty": true }, "rush": { "type": "boolean", "readOnly": true, "x-lt-section": "Facts", "x-lt-hide-if-empty": true }, "approved": { "type": "string", "enum": ["yes", "no"], "x-lt-section": "Action" }, "notes": { "type": "string", "format": "textarea", "x-lt-span": 2, "x-lt-section": "Action" } }}To render a section’s read-only facts as a compact definition list, see x-lt-display.
Column groups (x-lt-column-group)
Section titled “Column groups (x-lt-column-group)”In a two-column layout, consecutive fields that share an x-lt-column-group name render inside one grid cell as their own two-column pair, a 2×2 arrangement. One nesting level is supported. The token applies only when the schema layout is two-column.
{ "x-lt-layout": "two-column", "properties": { "width": { "type": "number", "title": "Width", "x-lt-column-group": "dimensions" }, "height": { "type": "number", "title": "Height", "x-lt-column-group": "dimensions" }, "notes": { "type": "string", "format": "textarea" } }}width and height share one cell of the outer grid, each taking half of it, and notes occupies a normal cell beside them.
Payload binding (x-lt-bind)
Section titled “Payload binding (x-lt-bind)”The form is flat; the payload a workflow consumes is often nested. A field’s x-lt-bind names the path its value occupies in the resolver payload (dot keys, optional [n] indices). On submit the dashboard maps the flat form through the binds; to prefill, it reverse-maps envelope.formDefaults through them. A field with no bind lands at its own name at the payload root.
{ "properties": { "customer_name": { "type": "string", "x-lt-bind": "customer.name" }, "contact_email": { "type": "string", "format": "email", "x-lt-bind": "customer.email" }, "tier": { "type": "string", "enum": ["starter", "professional"], "x-lt-bind": "contract.tier" }, "notes": { "type": "string", "format": "textarea" } }}Submitting { customer_name, contact_email, tier, notes } produces:
{ "customer": { "name": "…", "email": "…" }, "contract": { "tier": "…" }, "notes": "…"}The form is versioned on the role; the payload shape is the workflow’s own contract, produced by the binds. Change the form, its binds and the workflow’s resolver type in the same commit.
Help panel (x-lt-help)
Section titled “Help panel (x-lt-help)”Schema-level x-lt-help carries the form’s guidance (checklists, tier tables, callouts, links) as markdown. The dashboard renders it in the side panel beside the form, so the form stays a clean title-and-fields surface with the procedure one glance away. When a schema carries x-lt-help or x-lt-context, a help icon sits beside the form title and opens the panel’s Instructions view. The help text versions with the form: it lives in the same form_schema snapshot.
{ "title": "Customer intake", "x-lt-help": "### Review checklist\n\n1. Confirm the **legal name** matches.\n2. Send a test message before approving.\n\nThis escalation is **{{escalation.status}}** in the **{{escalation.role}}** queue.", "properties": {}}{{domain.path}} tokens
Section titled “{{domain.path}} tokens”Tokens in x-lt-help interpolate live values from the escalation:
| Domain | Resolves against |
|---|---|
escalation |
The escalation row ({{escalation.role}}, {{escalation.status}}) |
metadata |
The row’s metadata ({{metadata.schema_version}}) |
envelope |
The input envelope the workflow sent ({{envelope.min_score}}) |
payload |
The escalation context payload ({{payload.category}}) |
resolver |
The resolver payload as the person edits it ({{resolver.notes}}) |
A missing value renders as a dash. Links whose href starts with / navigate inside the dashboard.
Help fallback
Section titled “Help fallback”The panel’s Help view resolves in order: x-lt-help, then x-lt-context (plain text), then a state-aware hint (“Claim this escalation to enable the form”, “Fill out the form and submit to resolve it”). The resolver always has a prompt.
The panel’s other views show the record itself:
| View | Shows | Available to |
|---|---|---|
| Help | x-lt-help markdown, or a state-aware hint |
Everyone |
| Details | Status, role, priority, claim provenance, timestamps | Everyone |
| AI Analysis | Triage diagnosis and corrections | When AI is enabled and triage data is present |
| Metadata | The row’s metadata values | Everyone |
| Context | Input envelope, escalation context, resolver payload | Everyone |
| Errors | Pre-submission validation failures with click-to-focus | When submit is blocked |
| Record | The raw escalation JSON | Builders (admins, superadmins, engineers) |
Complete example
Section titled “Complete example”A two-column intake form with sections, a help panel, ordering and binds:
{ "title": "Customer intake", "description": "Complete all required fields, then submit.", "x-lt-layout": "two-column", "x-lt-order": ["first_name", "last_name", "email", "phone", "tier", "notes"], "x-lt-help": "### Intake checklist\n\n1. Confirm the **legal name** matches the ID on file.\n2. Send a test message to the email address.\n3. Select the tier from the sales order.\n\n> Route nonstandard contract language to legal.", "required": ["first_name", "last_name", "email", "tier"], "properties": { "first_name": { "type": "string", "x-lt-section": "Contact" }, "last_name": { "type": "string", "x-lt-section": "Contact" }, "email": { "type": "string", "format": "email", "x-lt-section": "Contact", "x-lt-bind": "customer.email" }, "phone": { "type": "string", "x-lt-section": "Contact" }, "tier": { "type": "string", "enum": ["free", "pro", "enterprise"], "description": "Select the customer tier", "x-lt-section": "Contract", "x-lt-bind": "contract.tier" }, "notes": { "type": "string", "format": "textarea", "x-lt-span": 2, "description": "Additional notes", "x-lt-section": "Contract" } }}