Skip to main content
State is client-side data that your UI can read and write. Components display state values, actions change them, and updates are instant — no server round-trip needed.

Setting Up State

Use set_initial_state() to define starting values. Any component in your UI can then read them through .rx or Rx() references: Drag the slider — the text updates instantly. The Slider has name="brightness", which means it automatically reads from and writes to the brightness state key. Most form controls (Input, Checkbox, Switch, Select, etc.) support this name prop for automatic state binding. For MCP tools, you can also provide initial state through AppResult.state:
AppResult State
from prefab_ui import AppResult

@mcp.tool()
async def settings() -> AppResult:
    return AppResult(
        view=...,
        state={"volume": 75, "muted": False},
    )

SetState

SetState explicitly sets a state key to a value. Both arguments are required — the key and the value to write:

Dot-paths

State keys can contain dots to reach into nested objects. profile.name means “the name field inside the profile object.” A purely numeric segment like 0 means an array index, so todos.0.done means “the done field of the first item in the todos array.” The name prop works with dot-paths too — type in the inputs below to see the card update: Integer segments address array items. Inside a ForEach loop, combine this with {{ $index }} to target the current row:
Array Paths
set_initial_state(
    todos=[
        {"text": "Find Magrathea", "done": False},
        {"text": "Have lunch", "done": True},
    ],
)

with ForEach("todos"):
    Checkbox(name="todos.{{ $index }}.done")
    Text("{{ $item.text }}")
SetState("todos.0.done", True) would also work for a hardcoded index — but {{ $index }} is how you target whichever row the user is interacting with.
If an intermediate path segment is missing or the wrong type (e.g. an integer segment pointing at a non-array), the update is a no-op with a console warning.

ToggleState

ToggleState flips a boolean — True becomes False, False becomes True. Pair it with If for show/hide patterns:

AppendState and PopState

AppendState adds an item to a state array. PopState removes one by index. Together with ForEach, they let you build dynamic lists entirely client-side. Type a name and click Add to see it appear in the list. Click × to remove a row. The “Add” button chains two actions: AppendState pushes the input value onto the array, then SetState clears the input. Each × button uses PopState with {{ $index }} — a variable provided by ForEach that gives the current row’s position. AppendState can also insert at a specific position with index=0 to prepend or negative indices to count from the end. If the key doesn’t exist yet, it creates a new array automatically.

Valid State Keys

State keys must be identifiers: letters, numbers, and underscores, starting with a letter or underscore (volume, _count, item_2). No hyphens (they conflict with expressions) and no periods (the dot is the path separator). These rules are validated in Python when you create the action.

API Reference

SetState Parameters

key
str
required
State key or dot-path to set (e.g. "count" or "todos.0.done").
value
Any
default:"\"{{ $event }}\""
Value to assign. Defaults to the value from the triggering interaction (slider position, input text, checkbox state, etc.).

ToggleState Parameters

key
str
required
State key or dot-path to toggle.

AppendState Parameters

key
str
required
State key or dot-path to the target array.
value
Any
default:"\"{{ $event }}\""
Value to append.
index
int | str | None
default:"None"
Insert position. None appends to end. Supports negative indices and template strings like "{{ $index }}".

PopState Parameters

key
str
required
State key or dot-path to the target array.
index
int | str
required
Index to remove. Supports negative indices and template strings like "{{ $index }}".

Protocol Reference

SetState
{
  "action": "setState",
  "key": "string (required)",
  "value?": "any"
}
ToggleState
{
  "action": "toggleState",
  "key": "string (required)"
}
AppendState
{
  "action": "appendState",
  "key": "string (required)",
  "value?": "any",
  "index?": "number | string"
}
PopState
{
  "action": "popState",
  "key": "string (required)",
  "index": "number | string (required)"
}
For the complete protocol schema, see SetState, ToggleState, AppendState, PopState.