The Instrument β Under the Hood
Why the motion rules are also performance rules, the contested entrance-animation decision, and how a design system fails.
In this deep dive
The rendering physics behind the aesthetic rules
DESIGN.md's motion constraints read like taste, but each maps to browser rendering mechanics:
| Design rule | Rendering consequence | Why it matters |
|---|---|---|
| Transform/opacity/background only β "never layout properties" | Compositor-thread animation; no reflow | Animating height or top forces layout for the whole subtree at 60 fps; transforms are GPU-composited and stay smooth even while JS is busy |
| Durations 120β400 ms, one 900 msβ4 s pulse | Bounded main-thread wakeups | Long ambient loops are allowed only when tied to real background work β idle CPU cost is budgeted like AI spend |
| Tabular numerals everywhere | Zero layout shift on count change | Proportional digits make "9β10" reflow the row; tabular-nums makes the tick a paint-only change |
Fonts via preconnect + display=swap | Text renders in fallback, swaps in β€1 frame | The instrument must never block on typography; self-hosting is logged as the pre-SaaS upgrade |
| Live timestamps tick "on the minute" | One timer, coarse granularity | Per-second updates would wake every row's component 60Γ more often for zero informational gain |
The count-gated tick is the subtle one: TickNumeral animates only when the value changes after mount β never on initial render. That's both a design law (the needle settle is the only entrance) and a performance law (a 50-row table animating on load is 50 simultaneous compositor animations for zero information). One gate serves both masters, which is the signature of a good constraint.
The decisions β including the contested one
Closed motion vocabulary + amendment process
Coherence survives new contributors and AI coding sessions β "is it in the table?" is a yes/no review question.
The hero moment (scoreboard tick) keeps its salience monopoly by law.
Legitimate new needs pay process overhead; the table must be maintained or it becomes fiction.
Motion guidelines ("be subtle, be purposeful")
No process; designers move fast.
Unenforceable in review; erodes one PR at a time until the product shimmers like a casino.
Ban all non-essential motion
Simplest law; zero ambiguity.
This was effectively v1 β and real user feedback ("feels static and inert") reversed it. The amendment (2026-07-14) is in the log with the research that informed it.
The needle-settle case rewards close reading: an entrance animation was banned by principle, proposed by one reviewer voice, kept banned by another, and finally allowed by the human with a scope so tight it can't metastasize β numerals only, 250 ms, once per page load, explicitly "so the scoreboard tick keeps its monopoly on choreography." That's how mature systems handle exceptions: not by pretending the rule has no tension, but by pricing the exception and fencing it.
Same pattern in the color decision: ember was removed from buttons entirely β trading away the easiest "make it pop" tool designers reach for, to protect the Pavlovian value of the scoreboard glow. Design tokens are an API; the budget is its rate limit.
How design systems fail (and how this one defends)
- Erosion by exception: each PR adds one "tiny" off-system choice; a year later the system describes nothing. Defense: findings-as-commits (
style(design): FINDING-004 β ember 'send now' label only when ready count is live) β violations get IDs, fixes get commits, the audit trail is git itself. - Reduced-motion as an afterthought: animations bolted on without the media query fail users with vestibular disorders. Defense: the rule is systemic (all motion inside
prefers-reduced-motion: no-preference; reduced users get a β€150 ms background/border change), and aMotionGatecomponent centralizes the check instead of trusting every call site. - The theme-flash race: any theming system has a first-paint problem β render before preferences load and users see a flash of the wrong theme. Wera dodged it by deferring dark mode entirely (logged decision: "the first memorable interaction is the number moving; dark mode doubles token QA before the core surface is proven"). Cutting scope is a concurrency fix too.
- Live timestamps vs. server render: "2m ago" computed on the server is stale by the time it hydrates β and mismatched text triggers hydration warnings. The
RelativeTimeclient component owns the ticking on the client; the server renders the stable absolute value. Time is the sneakiest source of server/client divergence in SSR apps. - Copy drift: a rule-based coach line means every state maps to exactly one sentence β but only while the counts feeding it are correct. Its inputs are the same derived queries as the scoreboard, so a needs-flag bug becomes a wrong sentence, the most human-visible symptom possible. Putting expressive surfaces downstream of derived state turns data bugs into legible ones.
The 2026-07-13 design review graded the product A- and still logged: H3s at 18px versus the documented 16/21 scale, a raw enum (github-public-list) leaking into UI, input backgrounds inverting the stated token pattern, nav touch targets under 44px. All polish-tier β and all catchable only because the system is written down. A design spec's deepest value is that violations become findable facts instead of arguments.
Make it yours
Audit a page against the constitution
Open Wera's /sources page (or any app you're building) with DESIGN.md beside it. Log every violation as a numbered finding: token used off-budget, numeral outside Plex Mono, motion not in the vocabulary, touch target under 44px. Fix the top three as separate, finding-referenced commits.
Hint
The TODOS.md "deferred design-review polish items" section shows exactly what this looks like when done by the project itself β match its format.
Amend the motion vocabulary
Wera needs a "CSV import progress" motion (rows appearing as they import). Write the amendment: the table row (trigger, properties, duration, easing token), the reduced-motion fallback, and the decisions-log entry β including which existing vocabulary entry it must stay quieter than, and why.
Hint
It's live background work β the run-pulse family, not a new hue or an entrance. Freshness warmth (700β1200ms, bg surfaceβtintβsurface) is probably your base.
Extend the coach β without breaking precedence
Add a rule to coachLine: if the user hit their weekly quota, celebrate once ("Quota met β anything now is a lead."). Decide where it ranks against the five existing rules, add it, and update coach.test.ts so every precedence boundary is pinned by a test.
Hint
Does a met quota outrank ready work? The product says no β finishing ready work beats celebrating. Your test should encode that argument, not just the happy path.
Compositor vs. layout-triggering properties β the mechanics behind "transform/opacity only."
The accessibility case for motion-off alternatives, from the standard itself.
tabular-nums lining-nums: the one-line CSS declaration carrying the "numerals are the brand" thesis.
You've walked a production codebase in its real build order: spec β riskiest link β data model β boundaries β pipelines β workflow β surface. The recurring moves β vertical slices, constraints as guarantees, errors as values, idempotency keys, quarantine, derived state, budgets β are the same seven ideas wearing different clothes. Go find them in the next codebase you open; they'll be there.