The palette that resized your app
Clicking a palette swatch is supposed to recolor a running app, live. For a while, on most apps, it recolored nothing — and instead made everything four times bigger.

Two programs, one variable name
Our design system's canonical structural token was named --spacing. It
turns out Tailwind v4's engine also defines --spacing on :root — as the
0.25rem unit step that sits behind every native utility: w-3 compiles to
calc(var(--spacing) * 3).
So when the palette push set --spacing: 1rem !important, it wasn't setting
our token. It was quadrupling Tailwind's base unit — every width, height,
padding, and gap in the app, all at once.
That explained the swatch incident. The uncomfortable discovery was the same
collision running in the other direction, quietly, for months: our runtime
remap sheet read var(--spacing, 1rem) expecting its own fallback, but found
Tailwind's 0.25rem instead — so p-4 rendered as 4px in every vibe, at rest.
The worst part: that bug was so consistent we had documented it. Our agent
runbooks carried a note that "vibe spacing is px-scaled," with a workaround —
generated apps learned to write px-[16px] instead of px-4. A documented
quirk in your runbook is often an undiagnosed bug wearing a lab coat.
The fix is namespacing (and calibration)
Naming a CSS custom property is an API decision, because :root is a global
namespace you share with your framework. The repair:
- The platform token became
--vibes-spacing— plumbing that can't collide. - Every remap fallback got recalibrated to stock Tailwind values.
- Layout-resizing tokens are held back from the recolor push entirely — a palette changes colors, never geometry.
- A
TOKEN_ALIASESmap (--bg→var(--background)) fans out so apps written in legacy vocabulary recolor too.
Get posts like this in your inbox
One email field. Real updates. No algorithm required.
When the bug is the contract
Correct fix, awkward consequence: every app authored during the quarter-scale months had been visually accepted under the wrong scale. Restoring stock Tailwind rendering landed on them as a 4× spacing change. When a bug becomes the rendering contract, fixing it is a breaking change — and you can't choose between repair and rollback until you can rank who breaks and by how much.
So before building anything, we counted. A scanner walked every app and
scored the damage by the numeric spacing utilities the runtime remaps
(arbitrary values like px-[16px] were never remapped — unaffected, and a
tell that the author had worked around the old scale). Then the same
heuristic ran over every live production app, straight from the database.
Two traps made the first numbers wrong, and they're the reusable lesson: skipping one of the two storage backends silently marked 86% of apps "not impacted" (13% jumped to 96% once both were fetched), and the obvious "recently updated" column turned out to be bulk-bumped by an unrelated process — only actual document writes tell the truth about which apps are alive.
Final census: 5,465 apps rendered differently after the fix — but the slice that was badly hit, actively used, and not trivially owner-repairable was 18 apps across 10 owners. The case for building a whole admin-repair capability dissolved once we counted. The counting script cost two orders of magnitude less than the tooling it replaced.
The ÷4 codemod that proves its own diff
For apps that did need repair, the tempting fix was a platform rollback. The right one was per-app repair — the old rendering was the bug, and rolling back would re-break palette recoloring and every future generation.
The repair is a 30-line codemod: divide every remapped numeric spacing step
by four; use the named Tailwind step when the quarter lands on the scale
(p-8 → p-2); use an exact-pixel arbitrary value when it doesn't (p-7 →
p-[7px] — the old rendering really was 7px).
Verification is the part worth stealing. Instead of eyeballing a 695-line diff, re-apply the codemod to every removed line and assert it reproduces the added line. 129 of 129 pairs matched — the diff provably contains nothing but the rewrite. Staged on a scratch copy, screenshot-compared, then pushed to the real app. A deterministic codemod plus a self-verifying diff turns a scary "fix the live app" into a mechanical operation.
What we keep
- Naming a CSS custom property is an API decision. Namespace your plumbing.
- A "documented quirk" with a workaround deserves a second look — it may be a bug that got promoted to policy.
- When a bug becomes the contract, measure the blast radius before choosing repair or rollback. The census is always cheaper than the tooling.
- Make repairs prove themselves: a codemod you can re-run against its own diff beats any amount of squinting.
Build on a platform that measures first
Describe an app, get it running in a minute — spacing intact.
Start building →