Skip to content

First app & components

Goal

Run a StreamTree app with a @component, state(), and render(Page(...)) so you have a mental model for every other recipe.

Install

pip install streamlit streamtree

(streamtree pulls Pydantic and typing-extensions; see Dependency strategy.)

Core ideas

  1. @component marks a function whose body runs on each Streamlit rerun when the tree is rendered. It returns elements (layout + widgets), not HTML strings.
  2. render(root) walks the tree and calls Streamlit primitives under the hood.
  3. Page is a common top-level container; Card, VStack, Text, Button compose the visible UI.

Minimal counter (full file)

The repository’s counter demo is the canonical “first app”. Full source:

"""Run with: ``streamlit run examples/counter.py`` from the repo root."""

from __future__ import annotations

from streamtree import component, render
from streamtree.elements import Button, Card, Page, Text
from streamtree.state import state


@component
def Counter():
    count = state(0, key="demo_counter")

    return Card(
        Text(f"Count: {count()}"),
        Button("Increment", on_click=lambda: count.increment(1)),
        Button("Reset", on_click=lambda: count.set(0)),
    )


def streamtree_tree_root():
    """Stable entry for ``streamtree tree examples.counter:streamtree_tree_root``."""
    return Page(Counter(), key="page")


if __name__ == "__main__":
    render(Page(Counter(), key="page"))

Run from the repository root:

streamlit run examples/counter.py

streamtree tree on the same tree

With pip install "streamtree[cli]" you can snapshot structure without running the UI:

streamtree tree examples.counter:streamtree_tree_root --summarize

See Testing & debugging for JSON snapshots in pytest.

Variations

  • Multiple components: nest Page(Header(), Body(), Footer()) where each child is a @component or plain elements.
  • Imperative Streamlit inside a component: you may call st.* in the component body, then return fragment() if the subtree is entirely imperative (see README “Using Streamlit inside components”).
  • App shell later: when you need st.set_page_config once, move to App + render_app (App shell, theme & context).

See also