{"version":"v1.0","client_state":{"DocsNavigation.default":{"fields":{"query":""},"persist":"memory","send_to_server":true},"ColorScheme.default":{"fields":{"mode":"system"},"persist":"local","send_to_server":true}},"endpoints":{"action":"/_bretzel/action","sse":"/_bretzel/sse","refetch":"/_bretzel/refetch"},"csrf":"e049dfd0908aa07d6a99070aae26fdde","page_id":"c8838abda827447a9194efd88b581411","address":""}

Describe the UI

Before making anything interactive, one has to know how to describe an interface. In Bretzel, a UI is a tree of Python components — static as long as no state moves.

Components composed with `with`

The `ui.*` components are functions. The containers (stack, card, grid…) open with a `with` block; their children are declared inside.
with ui.card():
    with ui.vstack(gap="sm"):
        ui.heading("Profile", level=2)
        ui.text("Member since 2024", color="muted")
        ui.button("Edit")
The complete list (inputs, overlays, tables, charts…) is inthe catalogue.

A page

A page is a function decorated with `@page` and its URL. A `@layout` draws the common frame (a sidebar, a header) and exposes a region through `ui.outlet()` where the pages render.
@page("/profile", layout=shell)
def profile() -> None:
    ui.heading("Profile", level=1)

Render from the state

The key point: the UI is built BY READING the state. One never modifies the display by hand — one describes what it must be for the current state. When the state changes, the UI is recomputed (that is reactivity, further on). The flow goes one way only: state → UI.
def cart_summary() -> None:
    cart = Cart()
    ui.text(f"{len(cart.items)} items")
    for item in cart.items:
        ui.text(item["name"])
Where does that state come from? That is next:Server state →