Phase 7 (AUD-149), cheapest first.
- internal/brand: vendored Simple Icons path data (CC0) for 50 marks, looked up
by the technology label the content already uses. Inline SVG, 16 px,
currentColor, no request and no font. tools/gen_brand_icons.sh regenerates it.
- Six hand-drawn area icons replace the two-letter badges in the nav and on the
landing cards; the evidence index gets a seventh.
- TechChips renders a mark where one exists and plain text where one does not,
so a missing icon reads as a decision rather than a broken image.
- Client wall: 45 names as one typeface, one size, one grid of equal tiles, and
the reason for no logo collage written on the page. No mark invented.
- Two diagrams, authored in-repo: homelab topology (platform-network.md) and
the RAG pipeline (ai-rag-corpus.md), each referenced from the page it explains.
- Content images now carry intrinsic width/height, loading="lazy" and
decoding="async" at render time; a site test fails the build if an image
ships without them.
- Topbar is two rows at desktop: the area names plus marks no longer overlap the
search form (Lighthouse target-size was failing at 1440 px).
- Favicon, so the browser stops requesting a missing /favicon.ico.
Satisfies: logos on every area page, area icons in nav and cards, two diagrams
referenced from their pages, images sized and lazy, Lighthouse >= 95 held.
(cherry picked from commit a473e4738a3751418c2097df2bcf0568fb6d0208)
One Go binary serves a pre-rendered site. No Node, no bundler, no node_modules:
htmx and the SSE extension are vendored files, Markdown and code highlighting
run at build time (goldmark + chroma), and the server only writes files.
Implements docs/phase-2-static-site.md:
2.1 service skeleton cmd/build (content -> dist), cmd/server (dist -> HTTP),
env-configured, 127.0.0.1:8096, /healthz with separate
static / ai / search readiness, --health-check probe,
deploy/compose.yml + deploy/Dockerfile at 120m
2.2 rendering templ components (Layout, Nav, PillarCard, Stage,
EvidenceTable, CodeBlock, Timeline, Footer);
`make generate` is a build step and is byte-stable
2.3 navigation six-area rail, <details> disclosure under 900px,
breadcrumbs, aria-current, L1/L2/L3 with artefact pages
2.4 stage panel internal/stage owns the contract; RouteDriver (fragment
swap) and SSEDriver (event stream) differ only in the
Binding, never in layout. fragment ids live in the
contract so route files, links and streamed frames agree
2.5 search SQLite FTS5 over titles and body, rebuilt by the build;
one handler returns a page without HTMX, a fragment with
it. Visitors' FTS operators are never honoured
2.6 quality floor print stylesheet, JS-off navigation, focus states,
semantic landmarks, dark default; security headers
Definition of Done evidence (see issue AUD-142):
A1 all pages 200 in a network namespace with no external route
one binary serves the site; make dist writes 45 pages, 86 fragments, 40 docs
templ generate is deterministic (md5 identical across runs)
6 L1 + 6 L2 pages, artefact pages reachable in <= 3 clicks
FTS5 returns sensible hits for zigbee / signage / routing (tested)
Lighthouse 100 performance and 100 accessibility, mobile and desktop
first byte well inside 100ms over loopback (test)
panel renders from a route driver and re-points at the stream untouched
print legible: /edge/ renders to a 3-page PDF with the print stylesheet
Also fixes found while finishing the build:
- reject "." / ".." path segments before ServeMux redirects them into a file
outside the asset directory (/static/../build.json now 404, was 307->200)
- make test is the real gate: go test ./... plus the validator self-test