Skip to content

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.

NounIsRole
Framea slicer — carves a box into sub-boxesstructure; the slide root and the fixed chrome-band sub-divisions
Cella typed slot — an empty, sized, positioned boxthe seam between a slicer and what fills it
Tilea filler — a leaf sized to fill one Cellthe terminal content (chrome, surfaces, or the author’s content)
Componentan authored layout (kpi, comparison, …)what fills the content Tile; it owns its own internal layout

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.

A 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.


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).

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.


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.

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.


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.


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:

  1. Parse (lib/engine/slides.js) — split on --- into a <section>; _class: kpiclass="kpi"; ## … → an <h2> as a direct child of the section; the list → <ol>, also a direct child. The DOM is flat — no cells yet.
  2. Transform (lib/transformers/registryapplyAllToHtml, then the Tile injectors) — this is where placement happens. The masthead-lift transform finds the first <h2> (+ eyebrow) and moves it into a .cell-masthead band (.masthead-lede + .masthead-bay). The <ol> body stays as direct section children (the stage). Tile injectors then add the chrome DOM (meta, progress, watermark).
  3. CSS layoutsection is a flex column at the resolved @size box; the masthead/stage/footer Cell CSS positions the bands via the --frame-* coordinate tokens; the Component CSS (section.kpi …) lays out the body; z flattens to z-index.
  4. 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.

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.