Single-tier app#
A flat sidebar of top-level destinations — the everyday “dashboard” app. Each sidebar item is an authored page; selecting it shows that page’s content. With a single set of pages, no workspace rail appears.
How it works#
add_page(key, *, text, icon) registers a sidebar item and its content page
together, and returns a context manager — widgets created inside the with
block are parented to that page. add_footer_page() pins an item (Settings,
Account) to the bottom of the sidebar. navigate(key) selects the starting page.
with shell.add_page("overview", text="Overview", icon="speedometer2"):
bs.Label("Overview", font="heading-lg")
shell.navigate("overview")
Example#
1"""Single-tier app — a flat list of top-level destinations (an analytics dashboard).
2
3Each ``add_page`` registers a sidebar item and its content together; the first
4``navigate`` picks the starting page. With one set of pages no rail appears — this
5is the everyday "sidebar app" shape.
6"""
7import bootstack as bs
8
9with bs.AppShell(title="Acme Analytics", size=(900, 580)) as shell:
10 shell.commandbar.add_label("Acme Analytics", font="heading-md")
11 shell.commandbar.add_spacer()
12 shell.commandbar.add_button(icon="circle-half", on_click=bs.toggle_theme)
13
14 with shell.add_page("overview", text="Overview", icon="speedometer2"):
15 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=12, padding=20):
16 bs.Label("Overview", font="heading-lg")
17 with bs.Grid(columns=3, gap=12, fill="x", sticky_items="ew"):
18 for label, value in (("Revenue", "$48.2k"), ("Orders", "1,204"), ("Visitors", "18.9k")):
19 with bs.Card(padding=16, gap=4):
20 bs.Label(label, font="caption")
21 bs.Label(value, font="heading-md")
22
23 with shell.add_page("reports", text="Reports", icon="bar-chart"):
24 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=8, padding=20):
25 bs.Label("Reports", font="heading-lg")
26 bs.Label("Build and schedule reports.")
27
28 with shell.add_page("customers", text="Customers", icon="people"):
29 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=8, padding=20):
30 bs.Label("Customers", font="heading-lg")
31 bs.Label("1,204 active accounts.")
32
33 with shell.add_footer_page("settings", text="Settings", icon="gear"):
34 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=8, padding=20):
35 bs.Label("Settings", font="heading-lg")
36
37 shell.navigate("overview")
38
39shell.run()
When to use#
Reach for the single-tier app when you have a handful of independent destinations and no need to sub-group them. If the destinations fall into clear categories, add section labels — see Grouped sidebar. If the sidebar is really a list of records (messages, devices), use Master–detail (list) instead. If the app has several distinct areas each with their own sidebar, give each a workspace — see Workspaces (rail).