Skip to main content
The Prefab protocol defines the JSON wire format exchanged between a server (Python SDK) and a client (renderer). A server returns a UIResponse that serializes to the envelope below. The renderer parses it, resolves templates, interpolates state, and renders the component tree.

Envelope

Every response is a JSON object with clean top-level keys:
State keys must not start with $ (reserved for interpolation builtins like $event and $error).

Components

Every component is a JSON object with a type discriminator:
All components share these optional base fields: Container components (Row, Column, Card, etc.) also have a children array of nested components. For conditional rendering, use the Condition component with cases and an optional else branch.

Actions

Actions define what happens on user interaction. They appear in event handler fields like onClick, onChange, and onSubmit. An action uses an action discriminator instead of type:
Action fields accept a single action, an array of actions (executed sequentially), or null:
Available action types:

Interpolation

All string properties support {{ key }} placeholders that resolve against client-side state at render time. The special value {{ $event }} captures the triggering interaction’s value (slider position, input text, checkbox state, etc.).

Define / Use (Templates)

Templates let you define a component subtree once and reference it multiple times with different data. Defining a template — entries in defs map a name to a component subtree:
Using a template — a $ref node references a definition by name:
With scoped data — add let bindings to the $ref node:
The renderer resolves $ref nodes by looking up the definition and rendering it with the current interpolation context. Circular references are detected and short-circuited.