DUNIN7 · Loomworks · Standing Note · Development Principle
No hardcoded CSS; the token set is the tunable surface
Every visual value a token — so a custom Companion re-skins by swapping tokens, and a theme editor can reach every pixel.
Version. v0.1 Date. 2026-06-26 Type. Standing note (development principle). Governs every frontend change request from here forward. Home. loomworks-record/standing-notes/
The principle in a paragraph
No hardcoded CSS values. Every visual value a component uses — color, font, spacing, corner radius — comes from a named token, never written directly into the component. The tokens live in one place; components refer to them by name.
Why it matters beyond tidiness
The goal is many custom Companions, each with its own look — and eventually a theme editor where someone tunes a Companion's appearance on a big screen with live preview. That feature is only possible if every visual value is a token. A single hardcoded value is a pixel the editor can't reach — it would stay fixed while everything around it changes. "No hardcoded CSS" is the precondition that makes a live theme editor buildable at all.
Decided now / deferred:color is tokenized repo-wide now (small, regular, the customization that matters most). Typography and spacing are known debt — 16 arbitrary font sizes with no scale; collapsing them is a design exercise, deferred to a later pass.
The principle (settled)
No hardcoded CSS values in component files. No raw hex or rgba(), no literal sizes in inline styles, no brand color or font written directly. Components consume tokens; the values live in tokens.css.
The token set is the tunable surface. Tokens are the API a future theme editor edits — named and organized to be read and tuned by a human, not a mechanical dump of extracted values.
Distinct colors are preserved as distinct, tunable tokens — not consolidated. Near-identical shades still each become their own token; consolidating destroys tunability before the tuner exists. The editor may later offer to merge; the tokenization does not pre-decide it. (Opposite of the typography rule — colors multiply into knobs; type sizes collapse into a scale.)
Typography and spacing conform to a designed scale, not a 1:1 tokenization. A handful of sizes, not sixteen. The type/spacing work is consolidation — design the scale, snap the app to it, discard the noise — so some sizes shift slightly as they snap. Deferred design work, not a find-replace.
A theme editor tunes a few meaningful knobs, never per-element values. Scale-level controls — a handful of colors, a type choice, a density setting — not a knob per value. Per-element customization is a non-goal. One control moves everything sharing the token.
Build for Loomworks first; tunability is the consequence. Tokens designed for the appearance Loomworks actually needs — not speculatively for hypothetical Companions. Build the real thing clean; it is swappable as a result.
Legitimate homes for literal CSS
src/styles/tokens.css — the sole legitimate home for raw color/font/spacing values (where they are defined).
src/app/globals.css — the token-wiring home; no raw color of its own.
Both are excluded from the guard. The guard scans component files (.tsx), where literal CSS is forbidden.
Done, deferred, named-future
Done / in progress: color tokenization. CR-2026-125 tokenizes TopBar and adds the two off-palette tokens (--color-vellum-soft, a gold). CR-2026-126 tokenizes every remaining color in src/ — including white and shadow as swappable tokens — leaving zero raw color outside tokens.css.
Deferred (named debt): the typographic + spacing scale. 16 arbitrary font sizes, no scale. A later design CR collapses them to a designed, editor-tunable scale. Recorded so it is not forgotten and not re-litigated.
Named future arc: the theme editor — big-screen tuning of a Companion's appearance with live preview. The reason the tokenization is built this way. Built when the foundation is ready; not now.
Guard (enforcement in code)
A static-scan test (the established vocabulary-wall pattern) over component files fails the build on raw hex / rgba() and on hardcoded brand literals outside the string registry. It catches what a line-scan reliably can; finer rules stay review-enforced where a scan would be over-broad. The guard's scope grows with the work — new files in CR-2026-125, repo-wide for color in CR-2026-126.