Skip to content

App shell, theme & context

Goal

Call st.set_page_config exactly once, compose sidebar + body as elements, and optionally inject theme CSS + shared context (app_context.provider).

App + render_app

Full demo:

"""Demo: App shell with page config, optional sidebar, and main body."""

from __future__ import annotations

from streamtree import component, render_app
from streamtree.app import App
from streamtree.elements import Button, Page, Text, VStack
from streamtree.state import state


@component
def SidebarNav() -> object:
    return VStack(Text("Sidebar"), Text("Use App + render_app for set_page_config."))


@component
def Main() -> object:
    n = state(0, key="app_shell_counter")
    return Page(
        Text("Main column"),
        Text(f"Counter: {n()}"),
        Button("+1", on_click=lambda: n.increment(1)),
    )


if __name__ == "__main__":
    render_app(
        App(
            page_title="App shell demo",
            layout="wide",
            sidebar=SidebarNav(),
            body=Main(),
        )
    )

Run:

streamlit run examples/app_shell.py

Theme variables

Use Theme, ThemeRoot, theme(), theme_css() (see streamtree.theme). Wrap subtrees that should pick up variables in ThemeRoot.

Shared values without prop drilling

app_context.provider during render installs values readable via lookup / streamtree.enterprise patterns (events, tenant id, redaction). Keep payloads small and JSON-friendly when you log or emit events.

Overlay elements

Dialog and Popover map to Streamlit st.dialog / st.popover when available; see examples/overlay_demo.py on the Examples page.

See also