Analyst Flow Demo
This page is the working reference for the systematic analyst flow: load the page dataset once → view it in a grid → select rows → a chart re-renders from the selection. Every cell below is a runnable {pyodide} cell, and the three cells are chained through dataflow declarations (#| define: / #| input:) in the cell options — nothing else connects them. Selecting rows in the grid re-executes the chart cell in place; the page never reloads.
How to read the decorations the dataflow runtime adds to connected cells:
- A pill row above a connected cell lists its declarations —
defines: …for published trigger tokens,inputs: …for the upstream names it consumes. Cells without declarations get no decoration. - A blue left border means the cell is running. While the dataset cell runs, its badge reads
loading ds_ready…, naming what is being loaded. - An amber border means the cell is blocked: it is waiting for an upstream (
waiting for upstream '…'/waiting for widget event '…') or a transitive upstream failed (blocked by failed upstream '…'). You will see this briefly during page boot — downstream cells sit blocked until the dataset cell publishes its token. - A red border means the error is the cell’s own: a Python exception or a malformed declaration, reported at the offending cell.
Step 1 — Load the page dataset once
One cell owns the data. load_page_dataset(name, loader) runs the loader exactly once per page visit and caches the frame, so every other cell works from the same loaded copy — the data here is inline and synthetic (seeded, so reloads reproduce it), no remote service involved. The cell publishes ds_ready, a primitive trigger token: #| define: carries only primitives (strings/numbers) across the worker boundary, while the DataFrame itself stays in the shared Python environment as the global ds.
Step 2 — View it in a grid
The grid cell declares #| input: [ds_ready], so it runs after the dataset cell publishes its token, and re-runs if the dataset cell is edited and re-executed. name="main" registers the widget with the event bridge: its row selection is published to the page as main_selection (payload shape {"rows": [...]}), cell edits as main_edits, and header-filter changes as main_filters.
Select a few rows by clicking or dragging the row-number gutter (the leftmost numbered column) and watch the chart below.
Step 3 — Chart the selection
The chart cell declares #| input: [ds_ready, main_selection], so every selection change in the grid re-executes it in place — no page reload. rows(ds, main_selection) decodes the selection payload into the subset of selected rows (with nothing selected it yields an empty frame). The cell charts the full dataset until you make a selection — select rows via the row-number gutter in the Step 2 grid and the chart re-renders with exactly the selected rows.
Seeing the error states
The flow above stays green, so this section documents one error surface with a scratch snippet instead of breaking the page. Paste this cell into any connected page (or a scratch copy of this one) to see the missing-input state:
```{pyodide}
#| input: [nonexistent]
nonexistent
```No cell on the page defines nonexistent and it is not a widget event channel, so the dataflow runtime marks the pasted cell red with the missing-reference error:
input ‘nonexistent’ is not defined on this page
The neighbouring states follow the same pattern: if an upstream cell exists but raises (for example, the dataset loader fails), its dependents turn amber with blocked by failed upstream 'ds_ready' instead of executing against stale data — the blocked badge always names the upstream at fault. Unaffected cells on the page keep executing normally.