web_themes #
Shared Web UI themes for ATProto CRA apps (altifier, verifier, sifter, ...). One repo to own the theme, apps pull it at build time — no more copy-paste drift between repos.
Structure #
web_themes/
scripts/sync-theme.sh build-time pull script (copy into consumers)
themes/
<theme-name>/
theme.css the theme: tokens + shared component styles
index.css body/base boilerplate (font, smoothing, transition)
Themes #
witchsky-cyan #
The original shared base theme from altifier + verifier (dark, cyan accent, 18px base font, WCAG AA, 48px touch targets). Altifier's home/login selectors are the superset, so it serves both apps.
Design tokens (defined in :root, components use var() only):
| token | value | use |
|---|---|---|
| --background | #111822 | page background |
| --text | #F9FAFB | primary text |
| --text-muted | #A5B2C5 | secondary text |
| --button-bg | hsl(174, 83%, 38%) | primary buttons, links |
| --button-text | #FFFFFF | text on primary buttons |
| --button-hover-bg | hsl(174, 78%, 32%) | primary buttons hover |
| --card-bg | #1C2B35 | cards, forms, inputs |
| --card-border | #394A58 | borders |
| --navbar-bg | #15232C | navbar, footer, inset fields |
| --success-bg | rgba(45, 242, 143, 0.12) | success status box |
| --success-text | #2CF28F | success text, approve btn |
| --success-border | rgba(45, 242, 143, 0.25) | success status box border |
| --error-bg | rgba(246, 90, 127, 0.12) | error status box |
| --error-text | hsl(348, 92%, 64%) | error text, destructive btn |
| --error-border | rgba(246, 90, 127, 0.25) | error status box border |
Shared component styles: body, typography, app/main containers, forms, inputs/selects, buttons, navbar, footer, home/login cards, status boxes, suggestions list, list items, revoke button (flash-red-warning), load-more, mobile media query.
Consuming a theme (build-time pull) #
-
Copy
scripts/sync-theme.shinto the consumer repo'sscripts/. -
Wire package.json:
"sync:theme": "bash scripts/sync-theme.sh", "build": "npm run sync:theme && react-scripts build", "start": "npm run sync:theme && react-scripts start" -
Import the synced files BEFORE the app's own CSS so app rules can override theme rules (index.js, imports are order-sensitive):
import "./styles/theme/index.css"; import "./styles/theme/theme.css"; import App from './App'; // App.css comes after — overrides theme -
Gitignore the generated copy: add
/src/styles/themeto .gitignore.
The script shallow-clones into ~/.cache/web_themes and copies
themes/<name>/theme.css + themes/<name>/index.css into
src/styles/theme/. Always pulls latest main. Override the repo with
WEB_THEMES_REPO (e.g. a local path for testing).
Adding a new theme #
- Create
themes/<name>/withtheme.css(tokens in:root, then component styles using onlyvar()) andindex.css(body base). - Keep the token NAMES stable across themes — consumers reference the variable names, not values. Only the values change per theme.
- Update this README's theme list.
Conventions #
- AGENTS.md is the primary agent instructions file.
- No hardcoded hex/Tailwind colors outside
:roottoken definitions; all component rules usevar(). Zero emojis in code/docs. - Any frontend design/polish/audit work loads the
impeccableskill first.