The layout library: a shader is a material, not a work — so the shelf holds fixed layouts with one slot left open, the ground. Browse by type, choose a fixed preset, then pair it with a material.
Cross-cutting laws·docs/compositions.md·241 lines
Kit src/components/compositions/Living example · Compositions
The law for the layout library — the shelf a finished material is paired with. It sits beside card-design-language.md, which governs how one card earns its surface; this document governs a narrower thing: a card or poster whose only open slot is the GROUND under it. The kit is src/components/compositions/ (a contract, a frame, a ground slot — deliberately nothing more); the layouts live under src/app/(workbench)/labs/compositions/layouts/ and register once in registry.ts; the living example is /labs/compositions, a full-screen pairing workbench — the composition on stage, materials beneath it, and a visual layout library beside it. The (workbench) route group opts out of the app shell without changing the public URL.
01
A shader is a material, not a work. So is a photograph, a gradient, a video. Graphic and interface design have always been "pick the layout, swap the ground", and the ground has always been allowed to be anything a material can be — except a shader, whose cost kept it out of the sequence. The cost is gone; the sequence is what this library supplies. A good shader alone is a demo. A good shader under a layout whose type stays legible over it is a piece, and a shelf of such layouts is what lets a family of shaders become a body of finished work rather than a folder of effects.
The library is therefore a CATALOGUE, not an editor. A layout is a fixed design — brought in one at a time, re-originated in the house language, its geometry and copy decided — with one thing left open. Geometry and copy remain fixed. Readers choose the ground and tone; Spot Card and Profile Card additionally expose one shared gradient-curve parameter, explicitly requested as a bounded exception to the no-knobs rule. It shapes the existing scrim without moving its start, end or content.
02
The first question is what the reader wants to make. Type answers that question (Hero, Profile Card, Spot Card, Metric Card). A preset is one fixed design within that type (Hero → Split, Editorial, Centered). Types are not component shells: presets in the same type may have different geometries and anatomies. A profile card with one preset is still a type; selecting it loads that design immediately, without a redundant second picker. A multi-preset type exposes its designs as thumbnails, rendered from the same components with neutral static grounds. There is no separate thumbnail geometry to drift.
Material and tone are independent choices. Switching type or preset preserves both. A preset belongs to exactly one type and registers once in the flat registry (type + preset); grouped shelves and counts derive from it. Empty types are not offered. Adding a second Profile Card preset automatically turns its single-design readout into a visual shelf; it requires no page edits.
Classification remains three orthogonal facts about each design. Anatomy still governs implementation, but it is no longer the primary browsing filter:
| Axis | Values | What it decides |
|---|---|---|
| Anatomy | Bleed · Panel · Inset | How the ground sits in the frame, and what the layout owes the type. |
| Subject | Profile · Metric · Product · Event · Quote … | What the piece is about — the text slots it carries. |
| Frame | card 3:2 · square · story 9:16 · poster 3:4 · wide 16:9 · banner 3:1 | The aspect the layout was designed for. Destinations are frame aliases, not folders. |
Hero is a use type, not a synonym for 16:9. A future portrait Hero can have its own frame without creating another category. Conversely, two 16:9 designs do not belong together merely because their dimensions match.
The three anatomies, and what each owes the type:
A layout that fits none of the three is a new anatomy, and a new anatomy is legislated here before its first layout is filed.
03
| Part | Owns | Lives at |
|---|---|---|
| Contract | The tone palette, the frames, the ground union, LayoutProps | src/components/compositions/contract.ts |
| Frame | The one container: Card's ring and shadow, an aspect ratio, a tone, size containment on both axes | frame.tsx |
| Ground | The material slot: five renderers behind one component, reduced motion, measurement for a live ground | ground.tsx |
| Layout | One fixed design: its own geometry, copy and scrim or panel, composing Frame and Ground | src/app/(workbench)/labs/compositions/layouts/<slug>.tsx |
| Registry | The one list: slug, title, type, preset, subtitle, anatomy, subject, frame, attribution, component | registry.ts |
| Grounds | The picker's presets — one of each material | grounds.ts |
04
Every layout obeys these; they are what make the shelf read as one product.
ELEVATION), pure shadow in light and shadow plus an INSET hairline in dark, and its radius is cqmin like everything else inside.cqmin. Every length inside the frame is a hundredth of the frame's short side. A layout is the same layout at 320px and at 1080px, which is what an export needs. The frame's container type is size for this; its aspect ratio supplies the height.backdrop-filter, never a mask over a live canvas, never a second translucent layer: a frosted pane re-samples the most expensive layer on the page every frame, and the scrim samples nothing.-dark twin is a second copy of one decision.05
A ground is handed { width, height, tone, reducedMotion } and returns pixels into the box. That is the whole interface, and its narrowness is the point:
Ground component; the layout mounts it and moves on.drift-ground.tsx, a CSS conic gradient turning under a blur) that exercises measurement, tone and reduced motion; it is there to be replaced, not extended.tone is passed so a live ground can choose its deeper palette for a dark surface rather than merely darkening.06
The workbench lives outside (app) in (workbench)/labs/compositions; the URLs /labs/compositions and /labs/compositions/<slug> stay intact. It is a catalogue workbench under workbench.md: a toolbar, stage and library, with a bounded scrim adjustment for opted-in designs rather than a full property inspector.
still; video presets display their poster. Only the stage mounts a live ground.material, tone and curve query parameters preserve the combination. Selection updates native history (integrated with Next's pathname/search hooks), so Back, Forward and refresh restore the same pairing without a second store. Curve previews are local only during a slider gesture; release commits one history entry. Invalid curves fall back to 100; finite values clamp to 0–100. Unknown material/tone values fall back to a known material and dark tone; unknown preset routes return 404. Old Profile Card and Metric Card links still work.07
Spot Card and Profile Card share EasedScrim and one gradientCurve prop. Registry metadata opts a preset into the control; Hero and Metric Card do not show it. The strength is 0–100: zero gives t, 100 gives smoothstep t²(3 − 2t), and intermediate values blend the two. One pure function drives both the visible curve and 33 sampled CSS opacity stops. Endpoints stay at 0 and 1, the fade stays monotonic, and no mask, blur or extra overlay is added. The initial strength is 100. Linear/Eased buttons provide exact endpoints; the slider supports continuous preview and keyboard adjustment. The setting persists when changing type, material or tone and is included in copied links.
Each layout still owns its geometry: Spot Card fades from 15% to 75% of its portrait height, following the supplied Jhey reference; Profile Card keeps its existing fade interval (42% to 76.8% of its 3:2 frame height). Thumbnails use the preset default. Reference-only comparison cards, underlay toggles and stop guides are not part of the catalogue; the curve preview explains the single parameter directly beside the selected artifact.
08
The intake is the same shape as filing a card in /labs/cards: one file, one registry line, no page edits.
after.Frame for the container, Ground for the slot, the palette for every colour, cqmin for every length. A Bleed layout writes its own scrim (direction, reach, where the action rides); a Panel layout its own cut.registry.ts. The shelf groups it by type; its preview, count and deep link follow automatically.09
ground.kind, or a scrim tuned to one photograph. The library stops radiating the moment a layout needs to know what it holds.backdrop-filter over a live canvas.profile-card-dark beside profile-card.reach slider, an anchor picker, a content editor. The moment a layout is parametric it is a generator, and a generator's output is the whole parameter space — which is mostly not good. The shelf holds decisions, not ranges.