Use one <VeltWireframe> registry in the whole app: everything else mixes without restriction.
The model
The four layers are not an app-wide setting. You choose per feature/surface, and you can combine them freely. Most real apps mix two or more. The core idea: pick the cheapest layer per feature, then layer CSS on top of everything for theming.The one rule for mixing
Use one <VeltWireframe> registry in the whole app: it may contain many feature wireframes. (Multiple are technically possible but merge first-with-content-wins: order-dependent and conflict-prone, so keep it to one; see R1.) Everything else mixes without restriction.
CSS variables apply globally, so they compose with any layer. Primitives, wireframes, and headless components can all coexist in the same app, even for related features.
Same-surface mixing is allowed and often useful. You can drop in a VeltCommentDialog primitive and use a wireframe to customize parts of that same dialog: for example, primitive everything, but wireframe a single leaf piece (leaf primitives have no sub-components, so their wireframe is the only way to restructure them). What matters is choosing intentionally per piece; there’s no rule against using more than one layer on a surface. (CSS is always layered on top regardless.)
Per-feature selection (how to think)
List your features, run the decision tree on each, record the result:
Different rows landing on different layers is normal and correct.
Common combinations
CSS + Primitives: “use it as-is, on-brand, in my design system”
Drop in Velt components, toggle features with props, wrap in your UI library, theme with--velt-*.
CSS + Wireframes: “custom layout, branded”
Override the slots you need; theme the result with one stylesheet. The most common combination in practice.Wireframes + Primitives: “custom dialog, default sidebar” (different surfaces, or same surface)
Wireframe one surface, use another as a plain primitive. Or, on one surface, use a primitive and wireframe a leaf piece of it. They don’t interfere.Wireframes + Headless: “custom UI + data-driven extras”
Wireframe the visible comment UI, and use a read hook to render something in your chrome (unread badge, counts, a custom filter control).Headless-only: “Velt is just the data layer”
No Velt UI at all; you render everything from hooks.A concrete mixed setup
<VeltWireframe>. This is a typical, healthy mix.
Anti-patterns
- ❌ Two
<VeltWireframe>roots. Merge first-with-content-wins → conflict-prone. Use one. - ❌ Headless for a feature a wireframe could do. Unnecessary maintenance: see
Headless. - ❌ Primitives just to restructure layout that wireframe slots already expose. More work for the same result: wireframe it.
- ❌ CSS
display:noneto remove a feature when a prop or wireframe would do it cleanly.
Note: mixing layers on the same surface is not an anti-pattern (e.g. primitive dialog + wireframe leaf). The anti-pattern is choosing a more expensive layer than the design needs.
What it can and can’t do
Checklist
- One
<VeltWireframe>total. - Cheapest viable layer chosen per feature/piece: CSS → Wireframes → Primitives → Headless (ran the decision tree on each).
- Each piece’s layer chosen intentionally (same-surface mixing is fine).
- One shared stylesheet for all
--velt-*theming +!importantoverrides.

