From 042868fec1f02a1effca23382721f4aabda48c54 Mon Sep 17 00:00:00 2001 From: Stuart Clark Date: Tue, 4 Aug 2026 11:24:51 +0000 Subject: [PATCH] feat(nuxt): show site version in footer and changelog in the h4ck panel --- .cspell.json | 6 + .gitignore | 3 + nuxt/DEV-TOOLS.md | 63 +- nuxt/app/components/DevGrid.vue | 722 ++------------------- nuxt/app/components/DevGridTools.vue | 712 ++++++++++++++++++++ nuxt/app/layouts/default.vue | 6 +- nuxt/content.config.ts | 8 + nuxt/nuxt.config.ts | 8 + nuxt/package.json | 4 + nuxt/scripts/getAppVersion.mjs | 16 + nuxt/scripts/sync-changelog.mjs | 29 + nuxt/tests/components/DevGrid.spec.ts | 639 +++--------------- nuxt/tests/components/DevGridTools.spec.ts | 667 +++++++++++++++++++ nuxt/tests/components/layout.spec.ts | 20 +- nuxt/tests/seo/seo.spec.ts | 48 ++ 15 files changed, 1736 insertions(+), 1215 deletions(-) create mode 100644 nuxt/app/components/DevGridTools.vue create mode 100644 nuxt/scripts/getAppVersion.mjs create mode 100644 nuxt/scripts/sync-changelog.mjs create mode 100644 nuxt/tests/components/DevGridTools.spec.ts 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 @@