client: show build version + browser diagnostics for bug triage

Fixes #68.

- Bar switcher and stats page get a low-contrast "wutzcalc <git-sha>"
  footer at the bottom (VersionFooter component, shared).
- Admin panel gets a fuller Diagnose section: version, user agent,
  screen resolution + device pixel ratio, viewport size, browser
  language.

Version is the short git commit sha, baked in at build time via
vite.config.ts define (falls back to "dev" if .git is unavailable at
build time, e.g. a tarball/CI-artifact deploy) - matches how deploys
actually run (pnpm build from a git checkout, per
deploy/wutzcalc.service), but stays defensive rather than failing the
build.

pnpm --filter client typecheck and build both clean.
This commit is contained in:
iris 2026-08-03 14:38:07 +02:00 committed by mara
commit 09e1bec9bb
7 changed files with 96 additions and 0 deletions

View file

@ -2,6 +2,7 @@ import { defineConfig } from 'vite';
import preact from '@preact/preset-vite';
import legacy from '@vitejs/plugin-legacy';
import { resolve } from 'node:path';
import { execSync } from 'node:child_process';
// The dev-server proxy target — same default (3000) as the server's own
// `process.env.PORT ?? 3000` in server/src/index.ts. Override with
@ -10,7 +11,23 @@ import { resolve } from 'node:path';
// WUTZ_SERVER_PORT=4000 pnpm dev:client
const serverTarget = `http://localhost:${process.env.WUTZ_SERVER_PORT ?? 3000}`;
// #68: baked into the bundle at build time so the client can show "which
// build is this" for bug triage without a server round-trip. Deploys run
// `pnpm build` from a git checkout (see deploy/wutzcalc.service), but this
// stays defensive against a tarball/CI-artifact deploy with no `.git` —
// falls back to 'dev' rather than failing the build.
function appVersion(): string {
try {
return execSync('git rev-parse --short HEAD', { cwd: __dirname }).toString().trim();
} catch {
return 'dev';
}
}
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify(appVersion()),
},
plugins: [
preact(),
legacy({