diff --git a/.cspell.json b/.cspell.json index c9c86090..dae3ea53 100644 --- a/.cspell.json +++ b/.cspell.json @@ -101,8 +101,14 @@ "wordmark", "crispedges", "mistagged", + "prerender", "prerendered", "prerendering", + "gtag", + "BRPZD", + "Standardised", + "modernised", + "repointed", "pathauto", "langcode", "onecol", diff --git a/.gitignore b/.gitignore index 7e31f5fc..b5b263dc 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ nuxt/.netlify # Playwright storage-state (session cookies) saved by screenshot-story.mjs nuxt/scripts/.auth/ + +# Generated by scripts/sync-changelog.mjs — CHANGELOG.md is the source of truth +nuxt/content/changelog.md diff --git a/nuxt/DEV-TOOLS.md b/nuxt/DEV-TOOLS.md index ca0d28b1..4136ddca 100644 --- a/nuxt/DEV-TOOLS.md +++ b/nuxt/DEV-TOOLS.md @@ -1,8 +1,11 @@ # stuar.tc Dev Tools -A secret dev-only overlay suite embedded in the site, available only -when running the local dev server (`import.meta.dev`). Activated via -the Konami code. Zero production footprint. +A secret overlay suite embedded in the site. Activated via the Konami +code, on every build — dev and production. Once unlocked, production +visitors see only the **Version** section below; the rest (Color +Scheme, Dev Overlay, Measure Tool, Module List, Client Data) stays +dev-only, gated on `import.meta.dev`, and its code never ships to +production visitors at all (see "Implementation notes"). ## Unlocking @@ -31,6 +34,15 @@ Authentication is session-only; it resets on page reload. After authenticating, clicking π opens the **Dev Console** (`H4CK TH3 PL4N3T`). +### Version + +The site's current version (from `CHANGELOG.md`) and a **Changelog** +toggle. Collapsed by default — expanding it renders the full release +history inline, in a scrollable box, without leaving the panel or +pushing the rest of the console (dev tools, in dev mode) below the +fold. There's no separate `/changelog` page; this is the only place +it renders. This section is available in production. + ### Color Scheme Switch the site's primary colour at runtime. Changes update every @@ -123,8 +135,22 @@ instead. ## Implementation notes -- All code lives in `app/components/DevGrid.vue` (rendered via - `` in `layouts/default.vue`). +- Split across two components. `app/components/DevGrid.vue` is the + shell: Konami detection, the π badge, the password modal, the + console frame, and the Version section — always rendered + (`` in `layouts/default.vue`, unconditional). + `app/components/DevGridTools.vue` holds the dev-only sections + (Color Scheme, Dev Overlay, Measure Tool, Module List, Client + Data), mounted from DevGrid only when `import.meta.dev` is true, + via Nuxt's `Lazy` component prefix (``) — its + code is a separate chunk, never fetched by production visitors. +- The changelog is fetched (`queryCollection('changelog')`) and + rendered (``) only once the console is + actually opened, and only rendered once the Changelog toggle is + expanded — both deferred so `@nuxt/content`'s rendering pipeline + isn't in every visitor's eager bundle for a panel most never find. + See `nuxt/scripts/sync-changelog.mjs` for how `CHANGELOG.md` + becomes a content collection in the first place. - Pure geometry utilities are in `app/utils/dev-measure.ts` — side-effect-free and independently unit tested. - Theme responsiveness uses @@ -136,11 +162,26 @@ instead. - Measure overlay uses a full-screen `pointer-events: all` div as a capture layer. `elementFromPoint` temporarily blinds the div (`pointer-events: none`) to hit-test the real page beneath it. +- DevGrid's own Escape handler covers the console/password modals + only. DevGridTools owns a second listener for its own overlays + (measure mode, static shell) — both toggles that open those + overlays also close the console first, so there's no ordering + dependency between the two listeners. +- A public, always-visible version indicator also lives in the site + footer (`@stuartclark/ui`'s `AppFooter`, `version` prop) — separate + from this panel, for visitors who never find the Konami code. + +## Future direction + +You've floated eventually splitting this into its own module with +multiple passwords unlocking different tiers — a public-safe one +(this one), separate secret ones, some behind 2FA. Not built yet; +tracked in `openspec/changes/tiered-dev-console-access/`. ## Testing ```bash -# Run all tests including DevGrid +# Run all tests including DevGrid/DevGridTools pnpm test # Coverage (must stay 100%) @@ -150,5 +191,11 @@ pnpm test:coverage Tests live in: - `tests/utils/dev-measure.spec.ts` — pure geometry utilities -- `tests/components/DevGrid.spec.ts` — component interactions - (konami, password, overlays, measure) +- `tests/components/DevGrid.spec.ts` — shell: konami, password, + console open/close, Version section, production-mode behaviour +- `tests/components/DevGridTools.spec.ts` — dev-only sections: + overlays, measure tool, color scheme, module list, client data +- `tests/seo/seo.spec.ts` — end-to-end check (real browser, real + Konami code) against the generated production build: footer + version text, no `/changelog` route, and the panel's changelog + content rendering inline once unlocked diff --git a/nuxt/app/components/DevGrid.vue b/nuxt/app/components/DevGrid.vue index 697d9e17..648ace32 100644 --- a/nuxt/app/components/DevGrid.vue +++ b/nuxt/app/components/DevGrid.vue @@ -1,12 +1,17 @@