# S06: App Footer with Version Info — Research

**Date:** 2026-03-30

## Summary

This slice adds a subtle app footer to every page showing version, build date, and an optional repo link. The work is straightforward — a single React component, ~30 lines of CSS, a Vite config change for build-time constants, and one line in `App.tsx`.

The app shell lives in `App.tsx` with `<header>` + `<main>` inside a `.app` div. The footer goes after `<main>`. Version comes from `package.json` (`0.1.0`). Build date and commit SHA need to be injected at build time via Vite's `define` option. The repo is `https://github.com/xpltdco/chrysopedia` (private, xpltdco org).

No backend changes needed. No new dependencies. No risks.

## Recommendation

Use Vite's `define` config to inject `__APP_VERSION__`, `__BUILD_DATE__`, and `__GIT_COMMIT__` as build-time constants. Create a small `AppFooter.tsx` component that reads these globals. Style it to be subtle — muted text, small font, centered, matching the dark theme.

For the git commit SHA: use `child_process.execSync('git rev-parse --short HEAD')` in `vite.config.ts` (runs at build time, not runtime). This is a standard Vite pattern — no library needed.

The repo link should point to the GitHub repo but since it's private, make it conditional or just display the short SHA as a link to the commit page (useful for the admin who has access).

## Implementation Landscape

### Key Files

- `frontend/vite.config.ts` — Add `define` block with `__APP_VERSION__` (from package.json), `__BUILD_DATE__` (ISO string), `__GIT_COMMIT__` (short SHA from git). Import `child_process` and `package.json` at top of config.
- `frontend/src/vite-env.d.ts` — Add `declare const __APP_VERSION__: string` etc. for TypeScript.
- `frontend/src/components/AppFooter.tsx` — New component. Renders version, build date, optional GitHub link. ~20 lines.
- `frontend/src/App.tsx` — Import `AppFooter`, render `<AppFooter />` after `</main>` inside `.app`.
- `frontend/src/App.css` — Add `.app-footer` styles (~15 lines). Use existing CSS custom properties: `--color-text-muted` for text, `--color-border` for top border, `--color-bg-page` background (or transparent). Font size `0.75rem`.

### Build Order

1. **Vite config + type declarations** — Add build-time constants. This is the only non-trivial piece (importing package.json version, running git command). Prove it works with `npm run build` or checking `import.meta.env`.
2. **AppFooter component + CSS** — Straightforward UI. Uses the constants from step 1.
3. **Wire into App.tsx** — One import + one JSX line.

### Verification Approach

1. `cd frontend && npm run build` — confirms Vite build succeeds with the new `define` values (no TS errors, no runtime errors).
2. Visual check at `http://ub01:8096` after Docker rebuild — footer visible on Home, Topics, Technique pages. Shows version like `v0.1.0`, a build date, and a short commit SHA.
3. Verify footer is subtle — doesn't compete with content, uses muted colors, proper spacing.

## Constraints

- `vite.config.ts` runs in Node context during build, so `child_process.execSync` is fine there. But the `define`'d values must be JSON-stringifiable (wrap in `JSON.stringify`).
- The private GitHub repo link (`https://github.com/xpltdco/chrysopedia`) is only useful for the admin. This is a single-admin tool, so it's fine to show it.
- The Dockerfile.web uses a multi-stage build (`node:22-alpine` → `nginx:1.27-alpine`). The git info must be available during the `npm run build` step. Since the `COPY frontend/ .` step only copies the frontend dir, git metadata won't be available inside Docker. The build arg pattern (`ARG GIT_COMMIT`) must be used in `Dockerfile.web` and passed from `docker-compose.yml`, similar to how `Dockerfile.api` already does it (per M006/S03 commit `12f9fb7`).

## Common Pitfalls

- **Git not available in Docker build** — The Dockerfile only copies `frontend/`, so `git rev-parse` will fail. Must pass commit SHA as a build arg. Fallback to `'dev'` if git command fails (for local dev without git, or CI without .git).
- **`define` values not JSON.stringify'd** — Vite's `define` does literal text replacement. String values must be wrapped in `JSON.stringify()` or they'll be injected as bare identifiers, causing runtime errors.
- **Footer pushing content on short pages** — Use a non-sticky footer approach. The `.app` container should have `min-height: 100vh` with flexbox to push the footer to the bottom naturally, without overlapping content.
