TL;DR
Maka's frontend has a proven governance pattern — converge contract tests that scan CSS/TSX and fail on bare values. Radius is the success story: 0 bare border-radius values, locked by radius-converge-contract.test.ts. But four dimensions still have large magic-number gaps: motion easing/duration, typography, spacing, and icon size. This issue converges them using the same proven pattern, after two independent reviews (OpenAI Codex + a fresh-context adversarial pass) caught real bugs and corrected the plan.
Two bugs were found during review and are folded in:
--ease-maka is a dead reference (ui.tsx:30 uses it, but it's never defined — the real token is --ease-out-strong).
--spacing: 0.25rem is 3.75px, not 4px — the comment /* 4px base step */ is wrong because html { font-size: 15px } makes 0.25rem = 3.75px. This means Tailwind's spacing scale (p-1 = 3.75px) and the hand-written padding: 8px in maka's CSS are two unrelated scales that don't match.
Current state
Already converged (don't touch):
| Dimension |
Status |
Guard |
| radius |
0 bare values |
radius-converge-contract.test.ts |
| z-index |
1 bare value (whitelisted) |
z-index-contract.test.ts |
| color / shadow |
uses tokens |
design-system-governance-406-contract.test.ts |
| motion (single curve) |
cubic-bezier(0.16,1,0.3,1) only in token decl |
motion-token-converge-contract.test.ts |
Gaps (this issue):
| Dimension |
Bare values |
Notes |
icon size={N} |
155 sites, 14 distinct values (11-28) |
makeIcon defaults to 1em already |
| font-size |
436 bare values |
only --font-size-base: 15px exists, no scale |
| spacing (padding/gap/margin) |
725 bare px |
--spacing defined but used 0 times |
| motion easing |
166 bare ease/ease-out/ease-in-out |
should use --ease-* |
| motion duration |
53 bare ms |
140ms (×21), 160ms (×11) are the actual high-frequency tuned values |
Benchmark
Three peer projects were analyzed (lobehub/lobe-chat, stablyai/orca, craft-ai-agents/craft-agents-oss). None of them have automated guards against bare values — they all rely on convention + component encapsulation (Tailwind default scale / antd tokens / shadcn CVA). Maka's converge-contract approach is unique and proven (radius = 0 bare). The plan extends that pattern rather than copying peer conventions.
What the two reviews caught
Review 1 (Codex):
- Changing
--font-size-base 15→14 is changing the root, which proportionally scales every rem and every Tailwind text-* class — a global visual regression, not a single-point tweak. → Keep root at 15.
- Full icon convergence violates
icon-system-contract.test.ts whose comments explicitly state dense/hero icons are "intentional, not drift". → Don't touch icons.
--ease-maka is a dead reference. → Fix it.
- 18px appears in multiple places (page padding, card gap, preview, sidebar), not just composer.
Review 2 (adversarial, fresh context):
--spacing: 0.25rem under a 15px root = 3.75px, not the 4px the comment claims. The "adopt Tailwind's 4px scale" premise was false. → Fix the --spacing value first.
- Spacing has no single-property anchor like
border-radius does. 18px spans 6 semantic contexts (padding, width/height, font-size, grid-columns, box-shadow, position). A blanket contract can't cleanly target only spacing.
140ms (×21) and 160ms (×11) are deliberately tuned feedback durations, all paired with --ease-out-strong. Excluding them from a 120/150/180/280 whitelist would force 32 gratuitous changes. → Don't force a duration scale.
10px (×47) forced to 12 is a +20% size increase on dense meta labels (timestamps, uppercase overlines). The owner accepts this.
Plan
One PR per dimension. Each PR combines governance (tokenize + contract lock) and value convergence, the way radius originally did. Value-changing steps (tier reduction, 18→16) carry screenshot verification within their PR.
PR 1 — motion (lowest risk, do first)
- Ban bare
ease/ease-out/ease-in-out/linear — must reference var(--ease-*).
- Fix
--ease-maka dead reference (ui.tsx:30 → --ease-out-strong).
- Do not force a duration scale: 140ms/160ms are tuned values; encourage
var(--duration-*) but don't ban them.
- Extend
motion-token-converge-contract.test.ts.
PR 2 — typography
- Body 15 (
--font-size-base untouched — avoids global rem scaling).
- UI tier 12; reduce 9/10/11/13 → 12 (the 47
10px meta labels grow +20%, owner-accepted).
- Headings via
em scaling off body 15 (h1-h4 ratios pinned in the PR).
- Introduce typography tokens + converge contract banning bare
font-size.
- Screenshot diff required (tier reduction changes dense meta density).
PR 3 — spacing
- First fix the
--spacing bug: 0.25rem (3.75px under 15px root) → absolute 4px so Tailwind's scale aligns with hand-written px.
- 18 → 16 (page padding, card gap, preview, sidebar).
- Define a px spacing scale + converge contract (targets
padding/gap/margin; spacing has no single-property anchor like radius, so the contract scopes to those properties).
- Screenshot diff required.
icon — no change
icon-system-contract.test.ts already correctly treats dense (12-14) and hero (20+) as deliberate call-site values. makeIcon defaults to 1em, tracking font-size automatically. Reopening the dense-tier design decision is a separate discussion.
Out of scope
- Component sizing (329 bare width/height): separate future evaluation. Spacing's 18px and sizing's 18px are coupled in some surfaces, so a sizing pass may revisit a few values landed in PR 3.
- User-configurable density: not doing.
- Full Tailwind migration: recorded as a future independent track. Maka is a hybrid (Tailwind primitives + hand-written CSS recipes with converge contracts); the contracts are stricter than Tailwind (Tailwind allows arbitrary
p-[13px], contracts don't), so a full rewrite isn't justified now.
docs/design-system.md rewrite: the doc is stale; refresh it as each PR lands, don't block on it.
Key decisions
- Root font-size stays 15 — changing it scales every rem globally (Codex finding).
- Motion duration isn't scale-locked — 140/160ms are tuned values (adversarial finding).
- Icons untouched — dense/hero are deliberate per existing contract (both reviews).
--spacing 3.75px bug fixed first — the "Tailwind 4px scale" premise was false (adversarial finding).
- One PR per dimension — governance (token + contract) and value convergence combined per dimension, like radius originally; value-changing steps carry screenshots.
Open assumptions
- The +20% growth on 47
10px meta labels (PR 2) is accepted; screenshot confirmation in the PR.
- 18→16 (PR 3) touches multiple surfaces; screenshot confirmation in the PR.
- Heading h1-h4 em ratios are finalized during PR 2 implementation.
TL;DR
Maka's frontend has a proven governance pattern — converge contract tests that scan CSS/TSX and fail on bare values. Radius is the success story: 0 bare
border-radiusvalues, locked byradius-converge-contract.test.ts. But four dimensions still have large magic-number gaps: motion easing/duration, typography, spacing, and icon size. This issue converges them using the same proven pattern, after two independent reviews (OpenAI Codex + a fresh-context adversarial pass) caught real bugs and corrected the plan.Two bugs were found during review and are folded in:
--ease-makais a dead reference (ui.tsx:30uses it, but it's never defined — the real token is--ease-out-strong).--spacing: 0.25remis 3.75px, not 4px — the comment/* 4px base step */is wrong becausehtml { font-size: 15px }makes0.25rem = 3.75px. This means Tailwind's spacing scale (p-1= 3.75px) and the hand-writtenpadding: 8pxin maka's CSS are two unrelated scales that don't match.Current state
Already converged (don't touch):
radius-converge-contract.test.tsz-index-contract.test.tsdesign-system-governance-406-contract.test.tscubic-bezier(0.16,1,0.3,1)only in token declmotion-token-converge-contract.test.tsGaps (this issue):
size={N}makeIcondefaults to1emalready--font-size-base: 15pxexists, no scale--spacingdefined but used 0 timesease/ease-out/ease-in-out--ease-*140ms(×21),160ms(×11) are the actual high-frequency tuned valuesBenchmark
Three peer projects were analyzed (lobehub/lobe-chat, stablyai/orca, craft-ai-agents/craft-agents-oss). None of them have automated guards against bare values — they all rely on convention + component encapsulation (Tailwind default scale / antd tokens / shadcn CVA). Maka's converge-contract approach is unique and proven (radius = 0 bare). The plan extends that pattern rather than copying peer conventions.
What the two reviews caught
Review 1 (Codex):
--font-size-base15→14 is changing the root, which proportionally scales everyremand every Tailwindtext-*class — a global visual regression, not a single-point tweak. → Keep root at 15.icon-system-contract.test.tswhose comments explicitly state dense/hero icons are "intentional, not drift". → Don't touch icons.--ease-makais a dead reference. → Fix it.Review 2 (adversarial, fresh context):
--spacing: 0.25remunder a 15px root = 3.75px, not the 4px the comment claims. The "adopt Tailwind's 4px scale" premise was false. → Fix the--spacingvalue first.border-radiusdoes. 18px spans 6 semantic contexts (padding, width/height, font-size, grid-columns, box-shadow, position). A blanket contract can't cleanly target only spacing.140ms(×21) and160ms(×11) are deliberately tuned feedback durations, all paired with--ease-out-strong. Excluding them from a120/150/180/280whitelist would force 32 gratuitous changes. → Don't force a duration scale.10px(×47) forced to 12 is a +20% size increase on dense meta labels (timestamps, uppercase overlines). The owner accepts this.Plan
One PR per dimension. Each PR combines governance (tokenize + contract lock) and value convergence, the way radius originally did. Value-changing steps (tier reduction, 18→16) carry screenshot verification within their PR.
PR 1 — motion (lowest risk, do first)
ease/ease-out/ease-in-out/linear— must referencevar(--ease-*).--ease-makadead reference (ui.tsx:30→--ease-out-strong).var(--duration-*)but don't ban them.motion-token-converge-contract.test.ts.PR 2 — typography
--font-size-baseuntouched — avoids global rem scaling).10pxmeta labels grow +20%, owner-accepted).emscaling off body 15 (h1-h4 ratios pinned in the PR).font-size.PR 3 — spacing
--spacingbug:0.25rem(3.75px under 15px root) → absolute4pxso Tailwind's scale aligns with hand-written px.padding/gap/margin; spacing has no single-property anchor like radius, so the contract scopes to those properties).icon — no change
icon-system-contract.test.tsalready correctly treats dense (12-14) and hero (20+) as deliberate call-site values.makeIcondefaults to1em, tracking font-size automatically. Reopening the dense-tier design decision is a separate discussion.Out of scope
p-[13px], contracts don't), so a full rewrite isn't justified now.docs/design-system.mdrewrite: the doc is stale; refresh it as each PR lands, don't block on it.Key decisions
--spacing3.75px bug fixed first — the "Tailwind 4px scale" premise was false (adversarial finding).Open assumptions
10pxmeta labels (PR 2) is accepted; screenshot confirmation in the PR.