Dark / Light / System theme with selector for marketing/ and docs-site/ #73

Closed
opened 2026-10-07 23:17:26 +02:00 by gotoi-agent · 5 comments
Collaborator

What

Add a theme system — dark, light, and system (follow OS) — plus a visible theme selector to
the two static surfaces:

  • marketing/ (repo root)
  • docs-site/ (Next.js + fumadocs, static export)

The main dashboard already has its own theme handling (system/dark/light + accent) — this issue
is about marketing and docs-site only.

Scope

  1. Audit what exists: both sites may already ship dark styles (fumadocs ships dark mode
    CSS; check whether a toggle exists). Record current state in the plan before designing.
  2. Persistence + init: choice stored (localStorage is fine for static export — no server
    state), applied before first paint (no flash-of-wrong-theme / FOUC), defaults to system
    for a new visitor.
  3. Selector: a small control in each site's header/nav — Dark / Light / System, current one
    marked; keyboard accessible; prefers-reduced-motion respected for any transition.
  4. Static-export safe: docs-site is output: export — no server routes, no dynamic
    rendering hooks that break the export. Verify with the site's build command.
  5. Both sites share the same three-state semantics and naming; if a shared snippet is
    genuinely reusable keep it simple — two small self-contained implementations are acceptable
    if sharing would add build machinery (say which you chose and why).

Gates

  • docs-site: its build (bun build → static export) must succeed, plus whatever checks exist
    in that package.
  • marketing: its own build/lint command (read marketing/package.json and run what exists).
  • Manual check described in the report: first load with OS dark → page dark; toggle to light →
    persists across reload; system follows an OS change.
  • One commit per surface or smaller, Refs #<N>, no closing keywords.
## What Add a theme system — **dark, light, and system (follow OS)** — plus a visible theme selector to the two static surfaces: - `marketing/` (repo root) - `docs-site/` (Next.js + fumadocs, static export) The main dashboard already has its own theme handling (system/dark/light + accent) — this issue is about marketing and docs-site only. ## Scope 1. **Audit what exists**: both sites may already ship dark styles (fumadocs ships dark mode CSS; check whether a toggle exists). Record current state in the plan before designing. 2. **Persistence + init**: choice stored (localStorage is fine for static export — no server state), applied before first paint (no flash-of-wrong-theme / FOUC), defaults to `system` for a new visitor. 3. **Selector**: a small control in each site's header/nav — Dark / Light / System, current one marked; keyboard accessible; `prefers-reduced-motion` respected for any transition. 4. **Static-export safe**: `docs-site` is `output: export` — no server routes, no dynamic rendering hooks that break the export. Verify with the site's build command. 5. **Both sites share the same three-state semantics and naming**; if a shared snippet is genuinely reusable keep it simple — two small self-contained implementations are acceptable if sharing would add build machinery (say which you chose and why). ## Gates - `docs-site`: its build (`bun build` → static export) must succeed, plus whatever checks exist in that package. - `marketing`: its own build/lint command (read `marketing/package.json` and run what exists). - Manual check described in the report: first load with OS dark → page dark; toggle to light → persists across reload; `system` follows an OS change. - One commit per surface or smaller, `Refs #<N>`, no closing keywords.
gotoi-agent added reference issue/73-theme-selector 2026-10-08 03:30:15 +02:00
Author
Collaborator

Claimed — branch issue/73-theme-selector. Doing: dark/light/system theme with a selector for marketing/ and docs-site/ (audit done: marketing ships a dark token ladder with no toggle; docs-site has fumadocs+next-themes but a 2-state toggle).

Claimed — branch `issue/73-theme-selector`. Doing: dark/light/system theme with a selector for marketing/ and docs-site/ (audit done: marketing ships a dark token ladder with no toggle; docs-site has fumadocs+next-themes but a 2-state toggle).
Author
Collaborator

Plan — issue #73: dark/light/system theme + selector for marketing/ and docs-site/

Branch issue/73-theme-selector, worktree /home/eduardez/workspace/gotoi-wt/issue-73.

Restated goal

Give both static GTM surfaces a three-state theme — light, dark, system (follow OS) — with the
choice persisted in localStorage, applied before first paint so there is no flash of the wrong theme,
and exposed through a small visible, keyboard-accessible selector in each site's header/nav. "Done" for the
operator: open either site on a fresh browser in dark OS mode → the page is dark on the first frame; click
Light → it turns light and stays light after a reload; pick System → it follows a later OS theme change.
No server state (both sites are static exports), no new dependencies, one commit per surface.

Audit results

marketing/ — tokens ship, no toggle, no init

  • marketing/src/app.css:163-213 — a complete dark token ladder under .dark, html[data-theme="dark"],
    and it already sets color-scheme: dark; @custom-variant dark (&:is(.dark *, [data-theme="dark"] *)) at
    line 14. @layer base html { color-scheme: light } (line 217) is the light default; the unlayered .dark
    rule outranks it, so color-scheme is already theme-correct in both directions. Reduced-motion block at
    lines 618-647.
  • marketing/src/app.html:8-9 — <meta name="theme-color" content="#fbfcfe"> and
    <meta name="color-scheme" content="light">, both light-only. The only script is a .js hydration
    watchdog (lines 10-17). No pre-paint theme script, no storage key, no toggle.
  • marketing/src/lib/sections/Nav.svelte — the floating nav pill: desktop section links, ml-auto group
    with the "Try Gotoi" CTA and a md:hidden menu button, plus a mobile panel (#mobile-nav).
  • No theme.ts/theme store in marketing/src/lib. Hardcoded light hexes: none found in
    marketing/src/**/*.svelte (the class="dark" product mocks in visuals/ConsoleWindow.svelte and
    sections/AiDeskDemo.svelte are intentional dark islands inside a light page — left alone).
  • Reference implementation to mirror in semantics and naming:
    dashboard/src/lib/theme.ts (ThemePreference = 'system'|'light'|'dark',
    THEME_STORAGE_KEY = 'gotoi-theme', parseThemePreference, resolveTheme, applyResolvedTheme) and
    the pre-paint block in dashboard/src/app.html (reads gotoi-theme, defaults to system, computes dark
    from matchMedia('(prefers-color-scheme: dark)'), toggles .dark + data-theme, wrapped in try/catch).
    Labels Light / Dark / System.

docs-site/ — full dark support, but only a 2-state toggle

  • docs-site/app/globals.css:71-90 — complete dark ladder (.dark:root, .dark) mapping --gotoi-* onto
    fumadocs' --color-fd-*. Nothing missing.
  • docs-site/app/providers.tsx — RootProvider (fumadocs) with search options only. fumadocs'
    RootProvider already wraps next-themes with attribute:"class", defaultTheme:"system",
    enableSystem:true, disableTransitionOnChange:true (fumadocs-ui/dist/provider/base.js). So
    persistence, the pre-paint inline script, and the "system" default are already in place —
    docs-site/app/layout.tsx carries suppressHydrationWarning for exactly that script.
  • docs-site/lib/layout.shared.tsx — exports baseOptions: BaseLayoutProps (spread into DocsLayout),
    without themeSwitch, so fumadocs defaults to mode: "light-dark" → the toggle rendered in the docs
    sidebar and mobile header is a two-state Sun/Moon button (aria-label="Toggle Theme", verified present in
    out/docs/*/index.html). fumadocs-ui/dist/layouts/shared/slots/theme-switch.js switches to the
    three-button Light/Dark/System variant when mode === 'light-dark-system', with per-button aria-labels.
  • docs-site/app/page.tsx:28-47 — the landing page has its own <header>; it is not a fumadocs layout,
    so it currently has no theme control at all.
  • output: "export" (docs-site/next.config.mjs) — no server routes; nothing planned needs one.

Conclusion: docs-site needs configuration + one placement (reuse the installed control). marketing needs
a real, small implementation (pre-paint init + selector + the pure resolve/apply helpers).

UC decision

No UC is authored. The catalog is three domains — middleware (which also hosts the OP cases),
frontend, agent — and docs/use-cases/domains.md contains no marketing/docs-site domain. The only cases
that mention docs-site/ (UC-OP-26 compose deploy, UC-OP-27 CI publish) cite docs-site/Dockerfile and
treat the site as a deployed artifact; theming a static GTM page is not their story. Authoring a new UC
here would invent a domain and a structure the repo does not have, which AGENTS.md forbids. Per the issue
prompt's own instruction ("If no UC domain covers marketing/docs-site and authoring one would be inventing
structure, say so explicitly"), I will state this in the plan and the report, cite UC-OP-26/UC-OP-27 in
the report only as the nearest existing references, and change no file under docs/use-cases/.
python3 docs/use-cases/_check.py is therefore expected to stay green as a no-op gate.

Scope

Files to change — exactly these:

Site File Change
marketing src/app.html pre-paint init script (gotoi-theme, default system, .dark + data-theme); theme-color metas split by prefers-color-scheme
marketing src/lib/theme.ts new — ThemePreference, THEME_STORAGE_KEY, parseThemePreference, resolveTheme, applyResolvedTheme
marketing src/lib/theme.test.ts new — vitest over the two pure helpers (parse whitelist, resolve matrix)
marketing src/lib/components/ThemeToggle.svelte new — three-state segmented control on installed Button + @lucide/svelte icons, aria-pressed, storage + matchMedia listener
marketing src/lib/sections/Nav.svelte mount the control (desktop row + mobile panel), bump Last
docs-site lib/layout.shared.tsx themeSwitch: { mode: "light-dark-system" } in baseOptions, bump Last
docs-site app/providers.tsx correct the now-false "light/dark" header comment, bump Last
docs-site app/page.tsx render fumadocs' ThemeSwitch (3-state) in the landing header, bump Last
docs-site app/globals.css prefers-reduced-motion guard for ::view-transition-* (fumadocs' switch uses startViewTransition), bump Last

Explicitly not touched: dashboard/, middleware/, agent/, plans/, deploy/, infra/,
scripts/, docs/use-cases/, docs-site/content/, marketing/src/app.css (its dark ladder and
color-scheme are already correct in both directions), and the intentional class="dark" product mocks in
marketing/src/lib/visuals/ and marketing/src/lib/sections/.

Sharing decision: two self-contained per-site implementations, as the issue permits. docs-site reuses
fumadocs' own control (zero new code beyond config); marketing gets one ~60-line component. A shared package
would add build machinery for ~60 lines.

Ordered tasks

  1. marketing helpers + test. Add src/lib/theme.ts and src/lib/theme.test.ts.
    Verify: cd marketing && bun run test.
  2. marketing control. Add src/lib/components/ThemeToggle.svelte; mount it in
    src/lib/sections/Nav.svelte (desktop row before the CTA, plus a row in the mobile panel).
    Verify: cd marketing && bun run check.
  3. marketing init. Add the pre-paint script and the theme-color metas to src/app.html.
    Verify: cd marketing && bun run build && bun run check, then rg -c 'gotoi-theme' marketing/build/index.html
    (the string must survive into the exported HTML).
    Commit: marketing: dark/light/system theme with a nav selector and pre-paint init Refs #73
  4. docs-site config + landing header. themeSwitch mode in lib/layout.shared.tsx, comment fix in
    app/providers.tsx, switch in app/page.tsx's header, view-transition reduced-motion guard in
    app/globals.css.
    Verify: cd docs-site && bun run build, then
    rg -o 'aria-label="(Light|Dark|System)"' docs-site/out/docs/index.html | sort -u (three buttons present)
    and rg -o 'aria-label="(Light|Dark|System)"' docs-site/out/index.html | sort -u (landing too).
    Commit: docs-site: three-state theme switch, system-following, reduced-motion safe Refs #73
  5. Gates. From repo root: python3 docs/use-cases/_check.py, python3 scripts/check-ai-headers.py,
    rg -n 'Showing lines' --glob '!node_modules' --glob '!.git' (must be empty), plus a final
    cd marketing && bun run build && bun run check and cd docs-site && bun run build.
  6. Report + Done comment to /home/eduardez/workspace/gotoi-wt/meta/issue-73.report.md and issue #73.

Open questions, with the assumption I proceed on

  • Where exactly does the marketing control live? Assumed: inside the nav pill (desktop, in the
    ml-auto group) and as a row in the mobile panel. A separate floating button would compete with the
    pill's chrome.
  • Which widget shape? Assumed: a segmented three-button group (aria-pressed each, all tabbable,
    native Enter/Space). It matches fumadocs' three-button variant and the dashboard's Light/Dark/System
    names, and it needs no roving-tabindex code that a role="radiogroup" would.
  • Does the docs-site landing page need the control? Assumed yes: it is a public entry point with its
    own header and no fumadocs layout, so without it the site root would have no theme control.
  • theme-color in marketing. The dark chrome colour is wired with a second media-scoped meta tag
    (follows the OS) rather than JS, so no extra code path can drift from the buttons.
  • Does the marketing store belong in a component or a module? Assumed: pure helpers (parse,
    resolve, apply) in src/lib/theme.ts so bun run test can cover them in the node environment;
    storage read/write and the matchMedia listener live in the component, guarded by onMount.

Risk and boring fallback

  • Hydration mismatch on the marketing toggle — the server renders system as active before
    onMount reads storage. Svelte 5 hydrates before onMount runs, so the correction is a post-hydration
    update, not a mismatch; the page colours are already correct pre-paint from app.html. Fallback: if
    bun run check or the build complains, move the "active" mark to a data- attribute applied in the
    same onMount and leave the button labels static.
  • fumadocs themeSwitch prop shape drift — if mode: "light-dark-system" does not produce three
    buttons after the build, fall back to slots.themeSwitch with an explicit <ThemeSwitch mode=... />
    from fumadocs-ui/layouts/shared/slots/theme-switch, or, at worst, render the same imported component
    in the landing header only and leave the sidebar at its default.
  • Landing-header layout on mobile — the new control is a fourth nav child; if the row wraps, wrap the
    links + switch + CTA in one flex items-center gap-4 div (keeps justify-between's two groups).
  • Static export — nothing planned requires a server hook; RootProvider and ThemeSwitch are
    "use client" and already ship in the current export.
  • AI-header checker — marketing/src/lib/components/ui/ is out of scope but every new marketing file
    I author is in scope, so all four new/edited marketing files and the four docs-site files carry the
    five-field header with a bumped Last.
# Plan — issue #73: dark/light/system theme + selector for marketing/ and docs-site/ Branch `issue/73-theme-selector`, worktree `/home/eduardez/workspace/gotoi-wt/issue-73`. ## Restated goal Give both static GTM surfaces a three-state theme — **light**, **dark**, **system (follow OS)** — with the choice persisted in `localStorage`, applied *before first paint* so there is no flash of the wrong theme, and exposed through a small visible, keyboard-accessible selector in each site's header/nav. "Done" for the operator: open either site on a fresh browser in dark OS mode → the page is dark on the first frame; click Light → it turns light and stays light after a reload; pick System → it follows a later OS theme change. No server state (both sites are static exports), no new dependencies, one commit per surface. ## Audit results ### `marketing/` — tokens ship, no toggle, no init - `marketing/src/app.css:163-213` — a complete dark token ladder under `.dark, html[data-theme="dark"]`, and it already sets `color-scheme: dark`; `@custom-variant dark (&:is(.dark *, [data-theme="dark"] *))` at line 14. `@layer base html { color-scheme: light }` (line 217) is the light default; the unlayered `.dark` rule outranks it, so `color-scheme` is already theme-correct in both directions. Reduced-motion block at lines 618-647. - `marketing/src/app.html:8-9` — `<meta name="theme-color" content="#fbfcfe">` and `<meta name="color-scheme" content="light">`, both light-only. The only script is a `.js` hydration watchdog (lines 10-17). **No pre-paint theme script, no storage key, no toggle.** - `marketing/src/lib/sections/Nav.svelte` — the floating nav pill: desktop section links, `ml-auto` group with the "Try Gotoi" CTA and a `md:hidden` menu button, plus a mobile panel (`#mobile-nav`). - No `theme.ts`/theme store in `marketing/src/lib`. Hardcoded light hexes: none found in `marketing/src/**/*.svelte` (the `class="dark"` product mocks in `visuals/ConsoleWindow.svelte` and `sections/AiDeskDemo.svelte` are intentional dark islands inside a light page — left alone). - Reference implementation to mirror in semantics and naming: `dashboard/src/lib/theme.ts` (`ThemePreference = 'system'|'light'|'dark'`, `THEME_STORAGE_KEY = 'gotoi-theme'`, `parseThemePreference`, `resolveTheme`, `applyResolvedTheme`) and the pre-paint block in `dashboard/src/app.html` (reads `gotoi-theme`, defaults to `system`, computes dark from `matchMedia('(prefers-color-scheme: dark)')`, toggles `.dark` + `data-theme`, wrapped in try/catch). Labels Light / Dark / System. ### `docs-site/` — full dark support, but only a 2-state toggle - `docs-site/app/globals.css:71-90` — complete dark ladder (`.dark:root, .dark`) mapping `--gotoi-*` onto fumadocs' `--color-fd-*`. Nothing missing. - `docs-site/app/providers.tsx` — `RootProvider` (fumadocs) with search options only. fumadocs' `RootProvider` already wraps `next-themes` with `attribute:"class"`, `defaultTheme:"system"`, `enableSystem:true`, `disableTransitionOnChange:true` (`fumadocs-ui/dist/provider/base.js`). So persistence, the pre-paint inline script, and the "system" default are **already in place** — `docs-site/app/layout.tsx` carries `suppressHydrationWarning` for exactly that script. - `docs-site/lib/layout.shared.tsx` — exports `baseOptions: BaseLayoutProps` (spread into `DocsLayout`), **without** `themeSwitch`, so fumadocs defaults to `mode: "light-dark"` → the toggle rendered in the docs sidebar and mobile header is a two-state Sun/Moon button (`aria-label="Toggle Theme"`, verified present in `out/docs/*/index.html`). `fumadocs-ui/dist/layouts/shared/slots/theme-switch.js` switches to the three-button Light/Dark/System variant when `mode === 'light-dark-system'`, with per-button `aria-label`s. - `docs-site/app/page.tsx:28-47` — the landing page has its **own** `<header>`; it is not a fumadocs layout, so it currently has no theme control at all. - `output: "export"` (`docs-site/next.config.mjs`) — no server routes; nothing planned needs one. **Conclusion:** docs-site needs configuration + one placement (reuse the installed control). marketing needs a real, small implementation (pre-paint init + selector + the pure resolve/apply helpers). ## UC decision **No UC is authored.** The catalog is three domains — `middleware` (which also hosts the OP cases), `frontend`, `agent` — and `docs/use-cases/domains.md` contains no marketing/docs-site domain. The only cases that mention `docs-site/` (`UC-OP-26` compose deploy, `UC-OP-27` CI publish) cite `docs-site/Dockerfile` and treat the site as a *deployed artifact*; theming a static GTM page is not their story. Authoring a new UC here would invent a domain and a structure the repo does not have, which AGENTS.md forbids. Per the issue prompt's own instruction ("If no UC domain covers marketing/docs-site and authoring one would be inventing structure, say so explicitly"), I will state this in the plan and the report, cite `UC-OP-26`/`UC-OP-27` in the report only as the nearest existing references, and change **no** file under `docs/use-cases/`. `python3 docs/use-cases/_check.py` is therefore expected to stay green as a no-op gate. ## Scope Files to change — exactly these: | Site | File | Change | |---|---|---| | marketing | `src/app.html` | pre-paint init script (`gotoi-theme`, default `system`, `.dark` + `data-theme`); theme-color metas split by `prefers-color-scheme` | | marketing | `src/lib/theme.ts` | **new** — `ThemePreference`, `THEME_STORAGE_KEY`, `parseThemePreference`, `resolveTheme`, `applyResolvedTheme` | | marketing | `src/lib/theme.test.ts` | **new** — vitest over the two pure helpers (parse whitelist, resolve matrix) | | marketing | `src/lib/components/ThemeToggle.svelte` | **new** — three-state segmented control on installed `Button` + `@lucide/svelte` icons, `aria-pressed`, storage + `matchMedia` listener | | marketing | `src/lib/sections/Nav.svelte` | mount the control (desktop row + mobile panel), bump `Last` | | docs-site | `lib/layout.shared.tsx` | `themeSwitch: { mode: "light-dark-system" }` in `baseOptions`, bump `Last` | | docs-site | `app/providers.tsx` | correct the now-false "light/dark" header comment, bump `Last` | | docs-site | `app/page.tsx` | render fumadocs' `ThemeSwitch` (3-state) in the landing header, bump `Last` | | docs-site | `app/globals.css` | `prefers-reduced-motion` guard for `::view-transition-*` (fumadocs' switch uses `startViewTransition`), bump `Last` | Explicitly **not** touched: `dashboard/`, `middleware/`, `agent/`, `plans/`, `deploy/`, `infra/`, `scripts/`, `docs/use-cases/`, `docs-site/content/`, `marketing/src/app.css` (its dark ladder and `color-scheme` are already correct in both directions), and the intentional `class="dark"` product mocks in `marketing/src/lib/visuals/` and `marketing/src/lib/sections/`. Sharing decision: **two self-contained per-site implementations**, as the issue permits. docs-site reuses fumadocs' own control (zero new code beyond config); marketing gets one ~60-line component. A shared package would add build machinery for ~60 lines. ## Ordered tasks 1. **marketing helpers + test.** Add `src/lib/theme.ts` and `src/lib/theme.test.ts`. Verify: `cd marketing && bun run test`. 2. **marketing control.** Add `src/lib/components/ThemeToggle.svelte`; mount it in `src/lib/sections/Nav.svelte` (desktop row before the CTA, plus a row in the mobile panel). Verify: `cd marketing && bun run check`. 3. **marketing init.** Add the pre-paint script and the theme-color metas to `src/app.html`. Verify: `cd marketing && bun run build && bun run check`, then `rg -c 'gotoi-theme' marketing/build/index.html` (the string must survive into the exported HTML). **Commit:** `marketing: dark/light/system theme with a nav selector and pre-paint init Refs #73` 4. **docs-site config + landing header.** `themeSwitch` mode in `lib/layout.shared.tsx`, comment fix in `app/providers.tsx`, switch in `app/page.tsx`'s header, view-transition reduced-motion guard in `app/globals.css`. Verify: `cd docs-site && bun run build`, then `rg -o 'aria-label="(Light|Dark|System)"' docs-site/out/docs/index.html | sort -u` (three buttons present) and `rg -o 'aria-label="(Light|Dark|System)"' docs-site/out/index.html | sort -u` (landing too). **Commit:** `docs-site: three-state theme switch, system-following, reduced-motion safe Refs #73` 5. **Gates.** From repo root: `python3 docs/use-cases/_check.py`, `python3 scripts/check-ai-headers.py`, `rg -n 'Showing lines' --glob '!node_modules' --glob '!.git'` (must be empty), plus a final `cd marketing && bun run build && bun run check` and `cd docs-site && bun run build`. 6. **Report + Done comment** to `/home/eduardez/workspace/gotoi-wt/meta/issue-73.report.md` and issue #73. ## Open questions, with the assumption I proceed on - **Where exactly does the marketing control live?** Assumed: inside the nav pill (desktop, in the `ml-auto` group) and as a row in the mobile panel. A separate floating button would compete with the pill's chrome. - **Which widget shape?** Assumed: a segmented three-button group (`aria-pressed` each, all tabbable, native Enter/Space). It matches fumadocs' three-button variant and the dashboard's Light/Dark/System names, and it needs no roving-tabindex code that a `role="radiogroup"` would. - **Does the docs-site landing page need the control?** Assumed yes: it is a public entry point with its own header and no fumadocs layout, so without it the site root would have no theme control. - **`theme-color` in marketing.** The dark chrome colour is wired with a second `media`-scoped meta tag (follows the OS) rather than JS, so no extra code path can drift from the buttons. - **Does the marketing store belong in a component or a module?** Assumed: pure helpers (`parse`, `resolve`, `apply`) in `src/lib/theme.ts` so `bun run test` can cover them in the node environment; storage read/write and the `matchMedia` listener live in the component, guarded by `onMount`. ## Risk and boring fallback - **Hydration mismatch on the marketing toggle** — the server renders `system` as active before `onMount` reads storage. Svelte 5 hydrates before `onMount` runs, so the correction is a post-hydration update, not a mismatch; the *page* colours are already correct pre-paint from `app.html`. Fallback: if `bun run check` or the build complains, move the "active" mark to a `data-` attribute applied in the same `onMount` and leave the button labels static. - **fumadocs `themeSwitch` prop shape drift** — if `mode: "light-dark-system"` does not produce three buttons after the build, fall back to `slots.themeSwitch` with an explicit `<ThemeSwitch mode=... />` from `fumadocs-ui/layouts/shared/slots/theme-switch`, or, at worst, render the same imported component in the landing header only and leave the sidebar at its default. - **Landing-header layout on mobile** — the new control is a fourth nav child; if the row wraps, wrap the links + switch + CTA in one `flex items-center gap-4` div (keeps `justify-between`'s two groups). - **Static export** — nothing planned requires a server hook; `RootProvider` and `ThemeSwitch` are `"use client"` and already ship in the current export. - **AI-header checker** — `marketing/src/lib/components/ui/` is out of scope but every new marketing file I author is in scope, so all four new/edited marketing files and the four docs-site files carry the five-field header with a bumped `Last`.
Author
Collaborator

DONE

Commits:

  • 1fdc243 marketing: dark/light/system theme with a nav selector and pre-paint init
  • 1033abd docs-site: three-state theme switch with system following

Gates:

  • cd docs-site && bun run build — PASS (static export, 20 routes)
  • cd marketing && bun run build — PASS
  • cd marketing && bun run check — PASS (451 files, 0 errors, 0 warnings)
  • cd marketing && bun run test — PASS (17 tests, 2 new)
  • python3 docs/use-cases/_check.py — PASS (no UC changed)
  • python3 scripts/check-ai-headers.py — PASS (576 ok, 0 missing)
  • rg -n 'Showing lines' — no hit in any authored file; the 9 matches are the rule's own documentation in AGENTS.md / RELEASING_INSTRUCTIONS.md / docs/**, pre-existing on develop.

Manual check (headless Chromium over both local static artifacts): fresh visitor with OS dark paints dark before first paint on both sites; clicking Light persists across reload on both; with System selected a synthetic OS colour-scheme flip re-renders both sites with no reload. Keyboard: marketing's three buttons are tabbable native buttons and Enter selects. Reduced motion: docs-site's view-transition cross-fade is pinned off under prefers-reduced-motion (rule present in the export).

Findings worth noting: docs-site already had a two-state toggle — the change there is mode light-dark-system plus the landing page, which had no control at all. No UC authored: the catalog has no marketing/docs-site domain and UC-OP-26/27 cover docs-site only as a deployed artifact. Storage keys differ by stack (next-themes 'theme' vs 'gotoi-theme'); say the word if you want them unified.

Report: /home/eduardez/workspace/gotoi-wt/meta/issue-73.report.md

DONE Commits: - 1fdc243 marketing: dark/light/system theme with a nav selector and pre-paint init - 1033abd docs-site: three-state theme switch with system following Gates: - cd docs-site && bun run build — PASS (static export, 20 routes) - cd marketing && bun run build — PASS - cd marketing && bun run check — PASS (451 files, 0 errors, 0 warnings) - cd marketing && bun run test — PASS (17 tests, 2 new) - python3 docs/use-cases/_check.py — PASS (no UC changed) - python3 scripts/check-ai-headers.py — PASS (576 ok, 0 missing) - rg -n 'Showing lines' — no hit in any authored file; the 9 matches are the rule's own documentation in AGENTS.md / RELEASING_INSTRUCTIONS.md / docs/**, pre-existing on develop. Manual check (headless Chromium over both local static artifacts): fresh visitor with OS dark paints dark before first paint on both sites; clicking Light persists across reload on both; with System selected a synthetic OS colour-scheme flip re-renders both sites with no reload. Keyboard: marketing's three buttons are tabbable native buttons and Enter selects. Reduced motion: docs-site's view-transition cross-fade is pinned off under prefers-reduced-motion (rule present in the export). Findings worth noting: docs-site already had a two-state toggle — the change there is mode light-dark-system plus the landing page, which had no control at all. No UC authored: the catalog has no marketing/docs-site domain and UC-OP-26/27 cover docs-site only as a deployed artifact. Storage keys differ by stack (next-themes 'theme' vs 'gotoi-theme'); say the word if you want them unified. Report: /home/eduardez/workspace/gotoi-wt/meta/issue-73.report.md
Author
Collaborator

REVIEW: CLEAN — findings: (1) plan scope fidelity exact — 9 files, none in/out of scope, 2 commits both 'Refs #73', no closing keywords; (2) repo-law checkers all green on re-run (_check.py, check-ai-headers.py 576 ok, check-type-mirror.py, 'Showing lines' hits are only the rule's own docs); (3) report claims reproduced — marketing check 451 FILES 0 ERRORS, bun test 17/17, exports contain gotoi-theme pre-paint + Light/Dark/System aria-labels + reduced-motion view-transition rule; (4) behavior verified live in headless Chromium against marketing/build and docs-site/out: fresh load OS dark -> dark, Light persists across reload, System follows OS flips on both sites, active state marked (aria-pressed / bg-fd-accent); (5) no test deleted/skipped/weakened; observation: docs-site storage key is next-themes 'theme' vs marketing/dashboard 'gotoi-theme' — semantics identical, implementer flagged it for a human, issue did not require key parity; UNFIXED: none

REVIEW: CLEAN — findings: (1) plan scope fidelity exact — 9 files, none in/out of scope, 2 commits both 'Refs #73', no closing keywords; (2) repo-law checkers all green on re-run (_check.py, check-ai-headers.py 576 ok, check-type-mirror.py, 'Showing lines' hits are only the rule's own docs); (3) report claims reproduced — marketing check 451 FILES 0 ERRORS, bun test 17/17, exports contain gotoi-theme pre-paint + Light/Dark/System aria-labels + reduced-motion view-transition rule; (4) behavior verified live in headless Chromium against marketing/build and docs-site/out: fresh load OS dark -> dark, Light persists across reload, System follows OS flips on both sites, active state marked (aria-pressed / bg-fd-accent); (5) no test deleted/skipped/weakened; observation: docs-site storage key is next-themes 'theme' vs marketing/dashboard 'gotoi-theme' — semantics identical, implementer flagged it for a human, issue did not require key parity; UNFIXED: none
Author
Collaborator

DONE — PR #77 opened against agent-develop: #77 | review: CLEAN (independent reviewer, 9router/reviewer) | gates (orchestrator re-run on final tree): docs-site build PASS, marketing build PASS, marketing check PASS, marketing test PASS (17/17), _check.py PASS, ai-headers 576 ok, type-mirror PASS, 'Showing lines' clean. Issue stays open — operator merges.

DONE — PR #77 opened against agent-develop: https://git.eduard3v.com/EduarD3V/gotoi/pulls/77 | review: CLEAN (independent reviewer, 9router/reviewer) | gates (orchestrator re-run on final tree): docs-site build PASS, marketing build PASS, marketing check PASS, marketing test PASS (17/17), _check.py PASS, ai-headers 576 ok, type-mirror PASS, 'Showing lines' clean. Issue stays open — operator merges.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
EduarD3V/gotoi#73
No description provided.