streaming-ui-script · project dashboard ← Back to docs
Live demo · rich patterns

A full engineering program dashboard, one statement per section

This single Streaming UI Script program drives an entire dashboard: announcement banner, page header with breadcrumbs and actions, KPI strip, kanban board, activity timeline, and follow-up chips. Every section reaches for a high-level pattern (PageHeader, MetricGrid, KanbanBoard, Timeline, Banner) instead of stitching primitives together by hand.

Live dashboard

Change the range or owner and the whole dashboard re-renders. Click a kanban card to mark it as the active item.

$range = "30d"
$assignee = "everyone"
$focusedCard = ""

data = Query("program_summary", {range: $range, assignee: $assignee}, {
  shipped: 0, inReview: 0, blocked: 0, velocity: 0,
  deltas: {shipped: "", review: "", blocked: "", velocity: ""},
  columns: [], events: [], blockers: []
})

banner = Banner(
  "v2.3 ships Friday",
  "Two hot bugs left in QA — see the board below.",
  Button("Open release", Action([@ToAssistant("Open the v2.3 release notes")]), "secondary", "button", "small"),
  "rocket",
  "info"
)

rangeField = FormControl("Range", Select("range", [
  SelectItem("7d",  "Last 7 days"),
  SelectItem("30d", "Last 30 days"),
  SelectItem("90d", "Last quarter")
], null, null, $range))

assigneeField = FormControl("Assignee", Select("assignee", [
  SelectItem("everyone", "Everyone"),
  SelectItem("ada",      "Ada Lovelace"),
  SelectItem("grace",    "Grace Hopper"),
  SelectItem("linus",    "Linus Torvalds")
], null, null, $assignee))

controlsRow = Stack([rangeField, assigneeField], "row", "m", "stretch", "start", true)

header = PageHeader(
  "Engineering · Q3 program",
  "Track deliverables across squads",
  Breadcrumb([BreadcrumbItem("Programs", "#"), BreadcrumbItem("Q3", "#"), BreadcrumbItem("Engineering")]),
  [Button("Export", Action([@ToAssistant("Export the dashboard as PDF")]), "ghost"), Button("New milestone", Action([@ToAssistant("Open the new milestone form")]), "primary")],
  Tag("On track", null, "sm", "success")
)

metrics = MetricGrid([
  StatCard("Shipped this week", "" + data.shipped,           "up",   data.deltas.shipped,  "rocket"),
  StatCard("In review",         "" + data.inReview,          "flat", data.deltas.review,   "eye"),
  StatCard("Blocked",           "" + data.blocked,           "down", data.deltas.blocked,  "circle-stop"),
  StatCard("Velocity",          "" + data.velocity + " pts", "up",   data.deltas.velocity, "bolt")
])

board = KanbanBoard(@Each(data.columns, "col",
  KanbanColumn(col.title, @Each(col.cards, "c",
    KanbanCard(c.title, c.description, c.tags, c.assignee, c.tone, c.icon, Action([@Set($focusedCard, c.title), @ToAssistant("Open card: " + c.title)]))
  ), col.tone)
))

timelineCard = Card([
  CardHeader("Recent activity", "Latest events across all squads"),
  Timeline(@Each(data.events, "e",
    TimelineItem(e.title, e.time, e.description, e.icon, e.tone)
  ))
])

blockersList = Card([
  CardHeader("Top blockers", "Need a decision this week"),
  List(@Each(data.blockers, "b", ListItem(b.title, b.owner, b.icon)))
])

bottomGrid = Grid([timelineCard, blockersList], 2, "l")

focusedNote = $focusedCard == "" ? null : Callout("info", "Focused card", $focusedCard)

followUps = FollowUpBlock([
  FollowUpItem("Drill into blocked items"),
  FollowUpItem("Send a weekly digest"),
  FollowUpItem("Compare to last quarter")
], "Try next")

root = Stack([banner, header, controlsRow, metrics, board, bottomGrid, focusedNote, followUps], "column", "l")

The single tool that drives everything

One Query("program_summary", …) call returns every shape the dashboard needs: KPI deltas, kanban columns, timeline events, blockers. The UI Script program is agnostic about how many columns or events come back — @Each over the arrays does the right thing.

el.setTools({
  program_summary: async ({ range, assignee }) => {
    await sleep(280);
    const totals = totalsFor(range, assignee);
    return {
      ...totals,
      columns: kanbanFor(assignee),
      events:  activityFor(range),
      blockers: blockersFor(assignee),
    };
  },
});