Design System

Overview

How it works

Where the design system actually lives, what moves between the pieces automatically, and what only moves because someone remembered to move it.

The pipeline today

parsed at buildnpm run sync (manual)no tokens generated — a person reads the prose and hand-writes the valuescontent/design.mdhand-authoredowned by this repothe stated SSOTrumor-design-systemfoundations · componentstokens · how it works/design.md raw routedesign.therumor.comweb-2.0Next.js · Tailwind v4→ Webrumor-mobile-expoReact Native · NativeWind→ iOS + Android
  • automated, every build
  • manual, run by hand
  • does not exist
Every arrow that reaches this site is real. Every arrow that leaves it for a product repo is a person retyping a number.

design.md is downstream

The intent is a straight line: design.md defines the tokens, the tokens generate the Tailwind and NativeWind layers, and the apps consume them. That line does not exist. No file in either product repo is generated from design.md, and nothing checks the two against each other.

What exists instead runs the other way. The sync script copies web-2.0's globals.css, its fonts, and a curated set of UI primitives into this site, and vendors the mobile app's generated export alongside them. Both are read-only and both are triggered by hand. So the documentation is assembled from the code it is supposed to govern, and design.md — the one file that is genuinely upstream — reaches production only by being read.

That is not an argument for deleting design.md. It is the argument for the next piece of work: a shared token package that both apps import, so the arrows out of this column stop being people.

One clarification the diagram makes on purpose: this is two codebases, not three. There is no separate Android design surface. web-2.0 renders Web; rumor-mobile-expo renders both iOS and Android from a single React Native codebase, so a decision made once in the mobile repo lands on two platforms.

Known gaps

Found by auditing the four repos against this document. Each one is real and each one has an owner-shaped fix.

  1. 01

    Every Semi Mono file in every repo is a trial cut

    The filenames are clean — ABCDiatypeSemiMono-Regular.otf — but the name table inside reads "ABC Diatype Semi Mono Trial". That is true of all three cuts in the mobile app, the one cut on the web branch, the three in collect, and the copies on this site. Semi Mono is already the body face of the mobile onboarding wizard, so this is shipping. Licence the family before it spreads further.

    all four repos — check name ID 4, not the filename

  2. 02

    The mobile app ships trial-licensed Romie too

    The binary registers RomieTrial-*.otf. Clean-named Romie-*.ttf files sit in the same folder, tracked but registered nowhere. Same class of problem as Semi Mono, only this one is visible from the filename.

    rumor-mobile-expo/assets/fonts, src/lib/fonts.ts

  3. 03

    Semi Mono is not a monospace

    It has 54 distinct advance widths — the mono is in the letterforms, not the metrics. Do not reach for it to align columns, and set tabular-nums wherever it renders a number that changes, or counts will jitter as they tick. The font does ship a tnum feature, so the fix is one class.

    anywhere Semi Mono sets numerals

  4. 04

    Semi Mono is missing from the expo-font plugin

    All three cuts are loaded through useFonts but absent from the expo-font list in app.json, so the body face alone loads at runtime instead of being embedded natively. Adding it is a native change and needs a version bump.

    rumor-mobile-expo/app.json

  5. 05

    One face, two token names

    Web calls it font-semi-mono; mobile calls it dia-mono, which reads as a monospace that does not exist. Settle on semi-mono. The mobile rename is roughly fifteen lines — the Tailwind config, the cn() font-family group, the ExpText table, and eleven call sites.

    web-2.0/app/globals.css, rumor-mobile-expo/tailwind.config.js

  6. 06

    web-2.0 has no text component

    Typography is raw utilities at every call site — no Text primitive, no CVA type variants. Mobile has a two-tier variant table in ThemedText and ExpText. There is nowhere on web to port that table to, which is the largest structural asymmetry in the system.

    web-2.0/components/ui

  7. 07

    Three font-family tokens resolve to nothing

    --font-sans is self-referential and --font-geist-mono is defined nowhere, so font-sans, font-mono, and font-heading apply an invalid family across 23 files. Harmless today only because the Diatype class also sits on the html element.

    web-2.0/app/globals.css

  8. 08

    A Romie migration by className override will not hold

    The mobile cn() helper lists the Diatype families in its font-family conflict group but not the Romie ones, so a className meant to override a ThemedText heading does not dedupe and the winner is decided by class order rather than last-wins.

    rumor-mobile-expo/src/lib/utils.ts

  9. 09

    This site is behind SSO

    design.therumor.com redirects to Vercel SSO, so it cannot be shared with anyone outside the team — including the people the system exists to align.

    Vercel project settings

  10. 10

    Vendored files drift by design

    globals.css, the fonts, the UI primitives, and the mobile export are copies. They are only as fresh as the last time someone ran the sync script. The real fix is shared @rumor/tokens and @rumor/ui packages.

    scripts/sync.mjs