Documentation
¶
Overview ¶
Package node is the JSON-clean UI element tree — the serializable description of a screen that renders to HTML via core-ui/noderender.
It is a first-party UI primitive. Both the blueprint codegen (cmd/gofastr) and Kiln's World IR (kiln/world) compose it; neither owns it. The package is deliberately dependency-free (stdlib only) so any layer can describe a node tree without dragging in a renderer or the Kiln authoring engine.
Index ¶
Constants ¶
const ( ActionNoop = "noop" ActionSetField = "set_field" // params: {field, value} ActionValidate = "validate" // params: {expression, message} ActionAudit = "audit" // params: {channel, message} ActionCreateEntity = "create_entity" // params: {entity, data} ActionRespondJSON = "respond_json" // params: {status, body} ActionRespondQuery = "respond_query" // params: {query} ActionEmitEvent = "emit_event" // params: {topic, data} )
Known Action kinds. Evaluators validate Kind+Params shape; serialization only requires that they round-trip through JSON unchanged.
Variables ¶
This section is empty.
Functions ¶
func AssignNodeIDs ¶
AssignNodeIDs walks the tree and assigns a stable ID to every node missing one. User-provided IDs are preserved; the idGen callback produces a fresh ID for nodes that need one. Idempotent: calling twice on the same tree is a no-op after the first call.
func FindNodeByID ¶
FindNodeByID returns a pointer to the node with the given ID, plus (parent, indexInParent) so callers can mutate sibling order. parent is nil and index is -1 when the matched node is the tree root. Returns ok=false when no node matches.
Linear walk over the tree — pages aren't large enough for this to matter; an index lookup would just add bookkeeping cost on every other op.
func NewElementID ¶
func NewElementID() string
NewElementID produces a fresh stable handle for a new node. The format ("el_" + 12 hex chars) is intentionally short for terminal readability and short tool calls; collisions inside a single page would require ~10^14 IDs to be likely, far beyond any plausible page size. Falls back to a counter-derived id on rand failure so callers never see an empty ID.
Types ¶
type Action ¶
Action is the canonical declarative effect type. The Kind selects from a closed verb catalog; Params is verb-specific. Treating actions as data — never Go source — is what lets consumers (journals, codegen, MCP tool surfaces) round-trip them losslessly.
type Node ¶
type Node struct {
ID string `json:"_id,omitempty"`
Kind string `json:"kind"`
Props map[string]any `json:"props,omitempty"`
Bindings map[string]string `json:"bindings,omitempty"`
Actions map[string]Action `json:"actions,omitempty"`
Children []Node `json:"children,omitempty"`
}
Node is a single element in a UI tree. The Kind discriminates between built-in elements ("div", "button", "heading", …) and named components ("component:<name>"). Props feed element configuration; Bindings express signal-driven values via expressions; Actions wire events to declarative effects.
ID is a stable per-element handle. Authoring tools (e.g. Kiln) reference it to address the exact element they want to mutate, rather than positional tree paths (which break when siblings shift) or selector queries (which can be ambiguous). The renderer ignores ID — it's pure metadata.