WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: update project context for user-theme-preferences branch

Document the theme resolution waterfall (now 5 steps with user
preference cookies) and the cookie protocol contract for
atbb-light-theme / atbb-dark-theme in CLAUDE.md.

+25
+25
CLAUDE.md
··· 181 181 } 182 182 ``` 183 183 184 + ## Theme Resolution & Cookie Protocol 185 + 186 + <!-- freshness: 2026-03-20 --> 187 + 188 + The web app resolves which theme to render via a 5-step waterfall in `apps/web/src/lib/theme-resolution.ts`: 189 + 190 + 1. **Detect color scheme** -- `atbb-color-scheme` cookie or `Sec-CH-Prefers-Color-Scheme` hint (default: `light`) 191 + 2. **Fetch theme policy** -- `GET /api/theme-policy` from AppView (cached in-memory with TTL) 192 + 3. **User preference** -- `atbb-light-theme` / `atbb-dark-theme` cookie (validated against `policy.availableThemes`; ignored when `policy.allowUserChoice` is false) 193 + 4. **Forum default** -- `defaultLightThemeUri` / `defaultDarkThemeUri` from policy 194 + 5. **Hardcoded fallback** -- neobrutal-light or neobrutal-dark bundled presets 195 + 196 + **Cookie contracts:** 197 + 198 + | Cookie | Written by | Contains | Max-Age | 199 + |--------|-----------|----------|---------| 200 + | `atbb-color-scheme` | Client-side JS (toggle button) | `light` or `dark` | 1 year | 201 + | `atbb-light-theme` | `POST /settings/appearance` | AT URI of chosen light theme | 1 year | 202 + | `atbb-dark-theme` | `POST /settings/appearance` | AT URI of chosen dark theme | 1 year | 203 + 204 + **Invariants:** 205 + - User preference cookies are always validated against the current `policy.availableThemes` on read. Stale or removed theme URIs silently fall through to the forum default. 206 + - `resolveTheme()` never throws -- it always returns a usable `ResolvedTheme`. 207 + - Settings routes (`/settings`, `/settings/appearance`, `/settings/preview`) require authentication. The preference form is only rendered when `policy.allowUserChoice` is true. 208 + 184 209 ## Middleware Patterns 185 210 186 211 ### Middleware Composition