Reference: Node Fields (what compile() reads)
Every field the compiler encodes, per node type. It is generated from chainc/node-schema.ts — the same table behind nodeJsonSchema(), checkNode(), vocabulary().nodeTypes and the MCP chainrender_check_node tool. That table is drift-locked to compile() in both directions: the TypeScript build fails if the compiler's node type gains a field the table doesn't list, and test/node-schema.ts changes every listed field and checks the compiled bytes change.
Why check a tree before compiling. compile() is lenient on purpose: it silently drops anything it doesn't read — an unknown field, a misspelled enum value (direction: "vertical", role: "note"), a11y fields on an image, args on a batch member. The tree still compiles, and the component ships without what was written. checkNode(tree) reports each of those with its path. See The Vocabulary.
Value kinds: address = 0x + 20 bytes · bytes32 = 0x + 32 bytes · hex = 0x + whole bytes · arg = hex bytes when resolver is set, otherwise free text for a client hook · integer = whole number ≥ 1 · number|string = a positive number or the same as a decimal string · record = a string-keyed map.
text
| Field | Value | Required | Note |
|---|---|---|---|
content |
string |
||
children |
node[] |
Also takes the accessibility fields and the behaviour fields (below).
box
| Field | Value | Required | Note |
|---|---|---|---|
direction |
one of row, column |
||
children |
node[] |
Also takes the accessibility fields and the behaviour fields (below).
button
| Field | Value | Required | Note |
|---|---|---|---|
variant |
one of primary, secondary, ghost, danger |
||
content |
string |
||
children |
node[] |
||
action |
object |
declared submit — gated by the enforcer (R3-R6); the label is never a guarantee on its own | |
action.to |
address |
||
action.sig |
string |
yes | function signature, e.g. "mint(uint256)" |
action.value |
string |
wei, decimal string | |
action.args |
string |
template the client fills, e.g. "$amount,0xSpender" | |
batch |
object[] |
atomic multi-action under one signature; requires BATCH_EXECUTE, each member gated individually; '|' and ';' are stripped from member fields | |
batch[].to |
address |
yes | |
batch[].sig |
string |
yes | |
batch[].value |
string |
wei, decimal string; defaults to 0 | |
batch[].label |
string |
consent-list label; defaults to sig | |
sign |
object |
EIP-712 typed-data signature; requires SIGN_MESSAGE; decoded before signing, never a blind hex sign | |
sign.domain |
object |
yes | |
sign.domain.name |
string |
||
sign.domain.version |
string |
||
sign.domain.chainId |
integer |
||
sign.domain.verifyingContract |
address |
||
sign.primaryType |
string |
yes | |
sign.types |
record |
yes | |
sign.message |
record |
yes |
Also takes the accessibility fields and the behaviour fields (below).
input
| Field | Value | Required | Note |
|---|---|---|---|
inputType |
one of text, number, password, search |
||
placeholder |
string |
||
content |
string |
Also takes the accessibility fields and the behaviour fields (below).
icon
| Field | Value | Required | Note |
|---|---|---|---|
name |
string |
Also takes the accessibility fields and the behaviour fields (below).
link
| Field | Value | Required | Note |
|---|---|---|---|
href |
string |
||
content |
string |
||
children |
node[] |
Also takes the accessibility fields and the behaviour fields (below).
slot
| Field | Value | Required | Note |
|---|---|---|---|
bind |
string |
yes | the resolver kind (e.g. "ensText") or a client hook name |
resolver |
address |
on-chain resolver; resolved during render | |
arg |
arg |
0x-hex resolver args when resolver is set (encode per the kind's descriptor); otherwise a display string a client hook reads |
|
content |
string |
fallback text |
Also takes the accessibility fields and the behaviour fields (below).
image
| Field | Value | Required | Note |
|---|---|---|---|
bind |
string |
||
resolver |
address |
||
arg |
arg |
0x-hex resolver args when resolver is set (encode per the kind's descriptor); otherwise a display string a client hook reads |
|
alt |
string |
the image's accessible text (images take no role/label) | |
provenance |
one of inline-vector, computed, onchain-blob, hash-pointer, external, onchain-vector-nft, computed-gpu |
Also takes the behaviour fields (below).
Images take no role/label/ARIA fields — alt is the image's accessible text. Those fields are dropped by compile() and reported by checkNode().
ref
| Field | Value | Required | Note |
|---|---|---|---|
hash |
bytes32 |
yes | ComponentRegistry content hash |
A ref takes only type and hash.
Accessibility fields
On every element type except image and ref.
| Field | Value | Required | Note |
|---|---|---|---|
role |
one of button, textbox, link, img, group, heading, tablist, tab, tabpanel, switch, dialog, listbox, option, radiogroup, radio, menu, menuitem, checkbox, region, alert, status, separator, tooltip |
ARIA role; tablist..separator opt the component into format V3, tooltip into V4 | |
label |
string |
aria-label | |
state |
object |
one ARIA state, emitted as aria- |
|
state.name |
one of selected, checked, expanded, modal, current, disabled, pressed |
yes | |
state.value |
bool |
yes | |
id |
string |
element id for relationships; opts into V3 | |
controls |
string |
aria-controls target id; opts into V3 | |
describedby |
string |
aria-describedby target id; opts into V4 | |
labelledby |
string |
aria-labelledby target id; opts into V4 | |
activedescendant |
string |
aria-activedescendant target id; opts into V4 | |
haspopup |
string |
aria-haspopup token ("menu" | "dialog" | ...); opts into V4 |
Behaviour fields
On every element type except ref (images included).
| Field | Value | Required | Note |
|---|---|---|---|
cond |
object |
render only when one resolver read matches; fail-closed | |
cond.resolver |
address |
yes | |
cond.bind |
string |
yes | |
cond.arg |
hex |
||
cond.equals |
string |
omit for a truthy test | |
cond.not |
bool |
||
step |
object |
a button's 1-based position in a state-driven flow (labels progress only) | |
step.index |
integer |
yes | |
step.total |
integer |
yes | |
anim |
object |
bounded declarative animation (no script) | |
anim.kind |
one of fade, pulse, spin, slide, blink, breathe |
yes | |
anim.duration |
`number | string` | |
anim.repeat |
one of once, infinite |
defaults to infinite | |
live |
bool |
viewer re-reads this element on new blocks (real chain state, never a stream) |
Fields compile() ignores
Allowed by the TypeScript type but never encoded; checkNode() reports them as ignored-field:
image:role,label,state,id,controls,describedby,labelledby,activedescendant,haspopupbutton.batch[]:args
Builder authoring fields
Read by the visual builder and grade(), never by compile(). checkNode(tree) reports them as authoring-field; checkNode(tree, { authoring: true }) and nodeJsonSchema({ authoring: true }) accept them.
argValuesonslotandimage(an object): the resolver args typed in the builder, by name; the builder encodes them intoargat export.image.scene(an object): the client-side sketch that runs above the on-chain floor.pinnedDepon the root node (an object): the pinned-dependency declarationgrade()reads (Grade B).- Any key starting with
_(for example_multiview,_view,_mvId): design-time metadata such as multi-view tabs.
Limits
- At most 1024 nodes and depth 64 (the interpreter's bounds).
- At most 255 children and 255 attributes on one node.
- Each literal value at most 65535 UTF-8 bytes.