Cells
A cell is how you look at assets. It holds no truth of its own: it points at one or more assets and says how to see them — this view, this size, this spot in the scene. Moving a cell, resizing it, deleting it — none of that touches what's true, which is why none of it asks for approval. Cells are cheap on purpose. Look at your assets ten ways; the assets don't notice.
Vocabulary note. On the wire, a cell is ascene_assetsrow plus the widget layer (WidgetData,widget.enrich,view_config) — the projection machinery predates the name. These docs teach the concept; the API reference documents the wire.
A cell has refs and a projection
A cell references assets and carries per-scene projection config: which named view, what size, where it sits (view_config on the scene link). The same asset can appear small in one scene and large in another, as a list here and a kanban there.
Cells render as 18 native shapes
Each projection produces a structured payload with a type discriminator; the client (iOS or web) renders each natively.
| Type | What it shows |
|---|---|
list | Rows with title, subtitle, optional badge and detail. The most common. |
table | Rows × columns with typed cells. For tabular data. |
key_value | Pairs grid. For "summary card" style. |
metric | Big number with optional trend, sparkline, label. |
chart | Line, bar, or area. Multiple series supported. |
record | Composite — header + highlights + pairs + items + footer. For invoices, POs, customer cards, anything entity-shaped. |
kanban | Items grouped into columns by a discriminator. Renders any view that returns a list. |
status | Health pill — healthy, unhealthy, expired. Used for accounts. |
document | Rendered markdown/text content. |
web | Embedded webview — a URL, or a cell the agent designed (below). |
console | Terminal-style output. |
calendar | Month/week/timeline view of dated events. |
map | Pins + polyline routes. Leaflet/MapKit-rendered. |
image | Single image, with intrinsic dimensions. |
video | Single video with native playback. |
gallery | Grid of images with select/label support. |
scene_3d | USDZ/USD model — RealityKit on iOS, AR QuickLook. |
plan | Step tracker — pending/in_progress/completed/failed/skipped. |
The record and kanban types are the two most flexible; most data shapes from real systems fit one of them.
Five sizes — and size decides what gets fetched
| Size | Cols × Rows | Apple equivalent | What it shows |
|---|---|---|---|
icon | 1 × 1 | app launcher | name + icon only — no fetch, just identity |
small | 2 × 2 | systemSmall | one scalar fact |
medium | 4 × 2 | systemMedium | top 3–5 items |
large | 4 × 4 | systemLarge | the primary view, full content |
xlarge | 8 × 4 | systemExtraLarge | iPad / desktop — primary view + secondary panel |
Bigger cells show more — and cost more: the pipeline skips fetching for icon cells entirely. A scene with 30 repos at icon knows they exist and pays no API quota; sizing one up is also choosing "keep this fresh." Use icon for "in the scene, but don't poll it."
Projections pull fresh data on load
Each asset type declares how a projection fetches — the enrich function runs for all eligible (non-icon) cells when a scene loads or refreshes, in parallel, and returns the render payload. The cell never caches a stale copy of the truth; it looks again.
The agent sees what the user sees
The agent's scene context lists cells with only the visible portion of each — the same per-size limits the renderer uses on screen:
| Shape | icon | small | medium | large | xlarge |
|---|---|---|---|---|---|
list items | — | 4 | 8 | 15 | 30 |
table rows | — | 3 | 6 | 12 | 25 |
kanban items / column | — | — | 3 | 6 | 12 |
record highlights | — | 2 | 3 | 5 | 8 |
record items | — | — | 3 | 8 | 15 |
document characters | — | 512 | 2,048 | 8,192 | 32,768 |
gallery images | — | — | 4 | 9 | 24 |
map pins | — | — | 5 | 15 | 50 |
metric / status / chart / key_value | — | full | full | full | full |
A — means name only. Truncated payloads carry a …showing N of M footer, so the agent knows there's more to fetch via tools on the asset.
Views are named lenses on an asset type
A github/repository declares views for pull_requests, issues, commits, contributors — separate projections of one asset, no separate sync. Static views are declared on the type; dynamic views resolve per-instance (a spreadsheet doesn't know its tabs until it's loaded).
Display cells project through functions
The composition move: a display cell references an input asset, picks a named view, and can override the rendering — the same pull_requests view as a flat list here, a kanban grouped by reviewer there, a metric that's just the count elsewhere. One asset, projected through functions, as many ways as the work needs.
When no shape fits, the agent designs the cell
The 18 shapes cover most of what real systems produce. For the rest, a cell can be a canvas the agent writes: full HTML — a dashboard over three assets, an approval cockpit, a form that feeds a workflow, a control panel for the lab. Ask for it in the conversation ("build me a cockpit for these") and the agent designs the view in place; it lives in the scene like any other cell, sized and positioned like any other cell, versioned in the commit chain like everything else.
Designed cells are how a scene grows views nobody shipped: your dashboards, your forms, your controls — drawn by the agent, owned by the scene.
Jobs update a designed cell by writing data, not HTML
A designed cell is stored as two parts: the view — the HTML the agent wrote — and its data, a small JSON document that lives on the cell. At render time the data is handed to the page (window.__DASLAB_WIDGET_DATA__), and the template draws it. To change what the cell shows, a job writes the data. It never touches the markup.
Take a bar chart of events per weekday. The agent designs it once — bars, labels, the load animation. From then on every update is seven numbers: a scheduled job refreshes them each morning, and when Monday spikes to 412, the same template tells that story. If the numbers are wrong, the fix is a data write; if the design is wrong, the agent edits the template once and every later write inherits it.
The split is what makes designed cells safe to automate. A job that edits HTML to change a number can break the view in a hundred ways; a job that writes data can only change what the data says. The write is also small enough to read in an approval — seven numbers, at a glance.
Native shapes have always worked this way: a list cell is data rendered by a view that shipped with the product. A designed cell has the same contract — the agent writes the view once, and from then on jobs only write data.
What's next
Updated 2026-07-20