# 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.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) 1. Copy `scripts/sync-theme.sh` into the consumer repo's `scripts/`. 2. 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" 3. 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 4. Gitignore the generated copy: add `/src/styles/theme` to .gitignore. The script shallow-clones into `~/.cache/web_themes` and copies `themes//theme.css` + `themes//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 1. Create `themes//` with `theme.css` (tokens in `:root`, then component styles using only `var()`) and `index.css` (body base). 2. Keep the token NAMES stable across themes — consumers reference the variable names, not values. Only the values change per theme. 3. Update this README's theme list. ## Conventions - AGENTS.md is the primary agent instructions file. - No hardcoded hex/Tailwind colors outside `:root` token definitions; all component rules use `var()`. Zero emojis in code/docs. - Any frontend design/polish/audit work loads the `impeccable` skill first.