streaming-ui-script · app workspace ← Back to docs
Live demo · AppShell + Sidebar + dense sections

A full SaaS workspace, generated from one program

This single Streaming UI Script program produces a complete product surface: a sticky Sidebar with sections + active state, a thin topbar with live status, a PageHeader, a MetricGrid KPI strip, a two-column content grid mixing Lists, StatusDots, a Timeline, and a DescriptionList — closing with follow-ups. Every section reaches for the matching pattern instead of hand-rolling layouts.

Live workspace

Click a sidebar entry to switch the focused page — the workspace re-renders with that page's KPIs, project list, and activity feed.

$active = "overview"

data = Query("workspace_overview", {page: $active}, {
  title: "", subtitle: "", status: "",
  kpis: [], projects: [], statuses: [], activity: [], summary: []
})

root = AppShell(nav, content, topbar)

nav = Sidebar([
  SidebarSection("Workspace", [
    SidebarItem("Overview",  "house", $active == "overview", null,  Action([@Set($active, "overview")])),
    SidebarItem("Projects",  "folder", $active == "projects", "12",  Action([@Set($active, "projects")])),
    SidebarItem("Calendar",  "calendar", $active == "calendar", null,  Action([@Set($active, "calendar")])),
    SidebarItem("Messages",  "comments", $active == "messages", "3",   Action([@Set($active, "messages")]))
  ]),
  SidebarSection("Insights", [
    SidebarItem("Analytics", "chart-pie", $active == "analytics", null, Action([@Set($active, "analytics")])),
    SidebarItem("Reports",   "chart-line", $active == "reports",   null, Action([@Set($active, "reports")])),
    SidebarItem("Billing",   "credit-card", $active == "billing",   null, Action([@Set($active, "billing")]))
  ])
], "Acme HQ", "Production · v2.3", [
  Stack([
    Avatar("Asha Patel", null, "sm"),
    Button("Settings", Action([@ToAssistant("Open settings")]), "ghost", "button", "small")
  ], 2)
])

topbar = [
  StatusDot("Realtime", "success", true),
  Buttons([
    Button("Invite",  Action([@ToAssistant("Invite a teammate")]), "ghost",   "button", "small"),
    Button("Upgrade", Action([@ToAssistant("Open the upgrade flow")]), "primary", "button", "small")
  ])
]

header = PageHeader(data.title, data.subtitle, null,
  [Button("New", Action([@ToAssistant("Open the new-item flow on " + $active)]), "primary")],
  Tag(data.status, null, "sm", "success"))

kpis = MetricGrid(@Each(data.kpis, "k", StatCard(k.label, k.value, k.trend, k.delta, k.icon)))

projectsCard = Card([SectionHeader("Active projects", null, "WORK", null,
  [Button("View all", Action([@ToAssistant("View all projects")]), "ghost", "button", "small")]),
  List(@Each(data.projects, "p", ListItem(p.title, p.subtitle, p.icon)))
])

statusCard = Card([SectionHeader("System status", null, "OPS", Tag("All normal", null, "sm", "success")),
  Stack(@Each(data.statuses, "s", StatusDot(s.label, s.tone, s.pulse)), "column", "s")
])

activityCard = Card([SectionHeader("Recent activity"),
  Timeline(@Each(data.activity, "e", TimelineItem(e.title, e.time, e.description, e.icon, e.tone)))
])

summaryCard = Card([SectionHeader("Workspace summary", null, "AT A GLANCE"),
  DescriptionList(@Each(data.summary, "d", DescriptionItem(d.label, d.value, d.icon)), 2)
])

contentGrid = Grid([projectsCard, statusCard], 2, "l")
detailGrid  = Grid([activityCard, summaryCard], 2, "l")
followUps   = FollowUpBlock([
  FollowUpItem("Show at-risk projects"),
  FollowUpItem("Open billing"),
  FollowUpItem("Invite my team")
])

content = [header, kpis, contentGrid, detailGrid, followUps]

One tool, every section

The whole workspace is driven by a single workspace_overview tool. The tool returns the title, subtitle, KPI list, project list, status pips, activity feed, and summary key/values for the active page. Swapping pages is one @Set($active, …) — no manual routing, no extra plumbing.

el.setTools({
  workspace_overview: async ({ page }) => {
    await sleep(220);
    return PAGES[page] ?? PAGES.overview;
  },
});