The Form model — Frame · Cell · Tile
A Lattice slide is composed, not just styled. One sentence is the whole system:
A Frame divides the slide into Cells; each Cell holds a Tile. The author’s Component fills the content Tile.
There are only two kinds of object — slicers (Frames) that make boxes, and fillers (Tiles) that fill boxes — joined by a typed slot, the Cell.
| Noun | Is | Role |
|---|---|---|
| Frame | a slicer — carves a box into sub-boxes | structure; the slide root and the fixed chrome-band sub-divisions |
| Cell | a typed slot — an empty, sized, positioned box | the seam between a slicer and what fills it |
| Tile | a filler — a leaf sized to fill one Cell | the terminal content (chrome, surfaces, or the author’s content) |
| Component | an authored layout (kpi, comparison, …) | what fills the content Tile; it owns its own internal layout |
1 · Frame → Cell
Section titled “1 · Frame → Cell”A Frame is, concretely, a cells: […] list (plus an optional suppresses: […]). The root standard frame composes the full chrome — a masthead band, the stage, and a footer row. A sovereign frame like split-panel keeps only the stage and suppresses the rest, so it reads as a completely different slide.
standardroot · full chromesplit-panelsovereignA slide has exactly one Frame — the root chrome frame, or a sovereign frame (like split-panel) that claims the whole canvas and suppresses the chrome. Cells hold Tiles; Frames do not nest inside content cells — that recursion was considered and rejected.
2 · Cell → Tile
Section titled “2 · Cell → Tile”A Cell is a typed slot — a sized, positioned region of the slide (the wireframe). A Tile is the leaf that fills one Cell, painted on a z-plane (z0 canvas · z1 atmosphere · z2 content · z3 chrome · z4 annotation — which flattens to z-index in 2D and would become literal depth in a spatial renderer).
- z0 canvas · rule
- z1 atmosphere · watermark
- z2 content
- z3 chrome title · meta · footer · progress · pagination
- z4 annotation
The author’s title and kicker (eyebrow) lift into the masthead-lede; the meta tile docks in the masthead-bay; the content Tile fills the stage; the footer-row Cells (footer-left, progress-centre, pagination-right) take the footer, progress, and pagination tiles.
3 · Tile → Component
Section titled “3 · Tile → Component”Almost every Tile is engine-owned chrome (title, meta, footer, progress, pagination, watermark…). The one exception is the content Tile (z2) — it hosts the author’s Component (kpi, comparison, …). The Component owns its own internal layout inside that Tile.
- Chrome tiles — engine-owned (title, meta, footer, progress, pagination…). The author never touches them.
- content tile — the engine-owned slot the author's markdown flows into.
- Component — the author's layout fills it, and owns its own internal layout. Portrait reflow lives here.
This is the seam that matters for responsiveness: orientation/reflow is a Component concern today (it lives in the component’s CSS), which is exactly why “does this layout work in portrait?” is a per-component fact.
4 · Putting it together
Section titled “4 · Putting it together”One Frame selects the Cells; each Tile paints into a Cell on its z-plane; the content Tile holds the Component. Stack the five planes bottom-to-top — canvas, atmosphere, content, chrome, annotation — and they composite into the slide.
- z4 annotation
- z3 chrome — title · meta · footer · progress · pagination
- z2 content tile → Component
- z1 atmosphere · watermark
- z0 canvas · rule
The render chain — one ## title, traced
Section titled “The render chain — one ## title, traced”The diagrams show the model. Here’s what the engine actually does with a slide an author writes — ## Revenue ahead of plan on a kpi slide:
- Parse (
lib/engine/slides.js) — split on---into a<section>;_class: kpi→class="kpi";## …→ an<h2>as a direct child of the section; the list →<ol>, also a direct child. The DOM is flat — no cells yet. - Transform (
lib/transformers/registry→applyAllToHtml, then the Tile injectors) — this is where placement happens. The masthead-lift transform finds the first<h2>(+ eyebrow) and moves it into a.cell-mastheadband (.masthead-lede+.masthead-bay). The<ol>body stays as direct section children (the stage). Tile injectors then add the chrome DOM (meta,progress,watermark). - CSS layout —
sectionis a flex column at the resolved@sizebox; the masthead/stage/footer Cell CSS positions the bands via the--frame-*coordinate tokens; the Component CSS (section.kpi …) lays out the body;zflattens toz-index. - Paint — the browser (or Puppeteer, for PDF) composites by z-plane → the slide.
The thing to internalise: Cells and Tiles don’t place anything at render time — transforms + CSS do, keyed on classes (form, kpi). The cell/tile manifests are the contract (validated by a build gate, surfaced in the catalog), not a layout engine that runs. That is the deliberate “light coupling” of the Form manifest contract.
Where orientation fits
Section titled “Where orientation fits”Because placement is transforms + CSS, orientation is too. Today a portrait/mobile deck stamps data-orientation on the section and the engine scales type (--canvas-scale) and reflows the grid layouts via component CSS (see social/mobile sizes). The natural next rung — Cells carrying portrait/landscape geometry (the wireframe reshapes), and Tiles + Components declaring the orientations they support — is captured in the ADR orientation in the Form model. The manifest can declare that a layout works in portrait; someone still writes the orientation-aware CSS/transform that makes it true.