Public: anyone can read this; nobody can change it.
Proposal: The wardrobe — themes you pick, not tokens you fork #238
Check · Review · Land · Live — No review yet.
proposal-the-wardrobe → main 1 commit
A guest
This pull comes from a guest: its preview runs without the app's variables or a forge token until a person who can write here approves it.
This pull waits for a person who can write here to review it; it never lands on its own.
1 file
changed +33
−0
docs/proposals/the-wardrobe.md added +33
| @@ -0,0 +1,33 @@ | ||
| 1 | # The wardrobe | |
| 2 | ||
| 3 | **Status:** proposal · **Companion to:** the design-token system (`design/tokens.default.json` → `/tokens.css`) | |
| 4 | **Problem:** every app carries its own copy of the named themes, and the forge chrome is themed by a different mechanism entirely. A "look" is scattered across repos and hand-edited in each — there is no catalog you pick from, only files you fork. | |
| 5 | ||
| 6 | ## What a look is today | |
| 7 | ||
| 8 | The token system is already good. Each app ships `design/tokens.default.json` (W3C design tokens, light + dark), compiles it to `/tokens.css` at boot, and an org's design app can override the vocabulary at runtime — every app re-skins with zero PRs. Named themes (`slate`, `dune`, `contrast`) live as `design/themes/*.json`. | |
| 9 | ||
| 10 | But the themes themselves are **copied into every app** from the template. Adding a look, or fixing one, means editing the same JSON in N repos. And the **forge** (Forgejo's own UI) is skinned by hand-written CSS with no relationship to the token vocabulary. The platform has a design system for apps and a separate paint job for the forge. | |
| 11 | ||
| 12 | ## What is missing | |
| 13 | ||
| 14 | - **No catalog.** There is nowhere to see, add, or pick a theme. A look is an artifact you copy, not a name you choose. | |
| 15 | - **Two surfaces, two mechanisms.** Apps use tokens; the forge uses ad-hoc CSS. A single "look" cannot cover the whole platform. | |
| 16 | - **Authoring is manual.** A complete theme is a large token set. Hand-writing every value per theme is why there are only three. | |
| 17 | ||
| 18 | ## The change: a wardrobe (`plat/themes`) | |
| 19 | ||
| 20 | 1. **One catalog repo.** Each theme is a small **`brand.json`** — a handful of seed decisions (accent, surfaces, type) — and a generator expands it into the full W3C token set. Adding a look is adding one brand file, not authoring hundreds of values. | |
| 21 | 2. **A look covers the whole platform.** The generator renders **two surfaces from one brand**: the app design tokens *and* the forge chrome CSS. Pick `dune` and the forge and every app wear it together. | |
| 22 | 3. **Picking is a choice, not a fork.** An org or app names a theme; the platform serves that theme's `/tokens.css`. The token vocabulary is never copied or diverged — themes alias the canonical roots, so a pick re-skins without forking. | |
| 23 | 4. **Stock looks ship in the box.** Neutrals (`slate`, `dune`), an accessibility theme (`contrast`), an `open-platform` default, and expressive options (`electric`, `neon-grid`) — so a new org has a wardrobe on day one, not a blank canvas. | |
| 24 | ||
| 25 | ## Why this shape | |
| 26 | ||
| 27 | - **One home per look.** A theme is defined once, in one file, and every surface reads from it — the same discipline as `one-home-per-fact.md`, applied to design. | |
| 28 | - **The vocabulary stays canonical.** Overrides alias the org-API token roots (`--color-accent`, …), so a theme re-skins the whole component library and the forge at runtime without diverging the contract. | |
| 29 | - **Picking is reviewable.** A look change is a one-line reference in a PR, with the rendered result visible in preview — not a hand-edit scattered across repos. | |
| 30 | ||
| 31 | ## Prior art (it already runs) | |
| 32 | ||
| 33 | A working wardrobe runs on a sovereign fork (`git.benjivers.com`): themes are generated from `brand.json` by a `generate.py`, and the **forge itself** wears generated themes — `neon-grid` and `electric` re-skin the live Forgejo UI from a generated CSS bundle, refreshed without a restart. This proposal upstreams that pattern: make the look a catalog the open platform ships, not a fork each operator paints by hand. |