CID and Views
CID (Column Item Display) is the layout primitive that drives most non-grid views in Race Platform. A CID layout is a tree of Section → Block → Line → Cell that the renderer walks once to produce a screen.
Why CID exists
A motorsport setup sheet, a tyre measurement form, a pit-window calculator — they all want the same thing: a dense, labelled grid of small numeric fields, grouped into logical sections, with each field driven either by a parameter value or by a math expression.
CID is the JSON description of that layout. Once you have CID, adding a new screen is editing JSON, not writing Flutter.
The tree
CID
└─ Section (e.g. "Front Suspension")
└─ Block (e.g. "Front Left Corner")
└─ Line (a horizontal row inside the block)
└─ Cell (one labelled value)
Each level can carry style overrides: title weight, background tint, column count, label position, etc. Cells can:
- Bind directly to a parameter (
Lap.parameters.BrakeTemp) - Compute via a math expression
- Display a static label
- Use a custom format string (see Format Strings)
Where CID renders
| Place | What CID drives |
|---|---|
| Run Sheet Setup tab | When a Setup Definition exists, the renderer is CID (toggleable with the hand-coded form via the segmented control) |
Custom Views of type cid | The whole view is a CID tree mounted at a custom path |
| Pit Window Calculator | Seeded as a cid custom view with 7 cells |
Custom Views — four view types
A Custom View has one of four viewType values:
| viewType | What it renders | Use case |
|---|---|---|
cid | A CID tree (Section / Block / Line / Cell) | Calculators, setup sheets, dense numeric dashboards |
cgd | A free-form layout-item tree (Border / Grid / Stack / Tab / Scroll / Expander / ItemsControl / ListView) | Free-form forms or screens where CID's strict tabular shape is too rigid |
single-table | A single-source table with column list, filter, sort, row-accent expression | "All laps for this session by sector 1 time" |
multi-session-table | A table that spans multiple sessions | "All laps across the event" |
The custom view also stores:
path— where it mounts in the router (/custom/...)icon— a Material icon name; mapped toIconDataby the shellsection— ribbon section the entry belongs to (championship/event/analysis/admin)enabled— whether the shell synthesises a feature spec for it
CGD — free-form layout
CGD (Custom Generic Designer) is the free-form sibling of CID.
Where CID enforces a strict Section / Block / Line / Cell shape,
CGD lets you compose any of nine layout items — border, grid,
stack, tab, tab-item, scroll, expander, items-control,
list-view — interleaved with the same cellSpec cell leaves CID
uses.
The runtime spec is a recursive CGDNode tree where each node is
either:
{ type: "layout", layoutType: "...", properties, children: [...] }{ type: "cell", cellSpec: { ... } }
CGD is intended for forms and dashboards that don't fit the flat-grid mental model. See the dedicated CGD Editor page for the property catalogue.
Live registration
When you save a Custom View, the shell's buildRouter watches the
provider and re-runs. Within seconds, your new view shows up in the
ribbon's sub-toolbar and the sidebar — no restart, no rebuild.
What you can do today
- Author CID layouts in Admin → Custom Views
(
/admin/custom-views). The CID editor supports full Section → Block → Line → Cell editing with add / remove / reorder. - Author CGD layouts in the same screen — the editor surfaces a recursive layout-item / cell tree.
- Author single-table custom views with column lists, filter expressions, row-accent expressions.
- Toggle Run Sheet's Setup tab between CID and hand-coded form via the segmented control.
- See the seeded Pit Window Calculator (
/custom/pit-window- calculator) for a working CID with 3 math parameters and a few literal cells. - See the seeded All Laps view (
/custom/all-laps) for a multi-session-table example.
What's coming
- CGD ItemsControl / ListView data binding — the shapes
render today; binding their
itemsSourcePathagainst live scope is partially wired. - Cell-level expression binding to related entities — the
filter expression already runs in a permissive scope but doesn't
yet see joined related rows (e.g.
Lap.Session.BestLapTimeMs). Joined scope is in the queue. - CID print / export — the renderer is screen-only today.