feat(infra): local serve-static profile — Caddy reverse proxy for the prod build #97
Reference in New Issue
Block a user
Delete Branch "feat/infra/local-serve-static"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Add a Caddy reverse proxy behind a new
--profile serve-staticso a contributor can exercise the production build locally with the per-locale routing the on-prem reverse proxy will use (per ADR-0019). Closes the gap surfaced by PR #96: the locale switcher / accessibility route fusion / cookie plumbing all need a prod-faithful local setup, andnx serve-staticfalls short (no SPA fallback per locale, no smart/redirect, exposes thehttp-serverdirectory-listing footgun we hit during the perf-gate fix in PR #92).What lands
infra/local/Caddyfile— explicitrouteblock:GET /→ 302 to/{locale}/based onAccept-Language, falling back to/fr/(APF audience)./fr/*→dist/.../browser/fr/with SPA fallback tofr/index.html./en/*→ mirror./fr/.infra/local/dev.compose.yml— newserve-staticservice on theserve-staticprofile. Bind-mounts the Caddyfile anddist/apps/portal-shell/browser/read-only. Port 4200, overridable viaSERVE_STATIC_PORT.infra/local/.env.example— addsSERVE_STATIC_PORT=4200.infra/local/dev.sh— registersserve-staticinALL_PROFILESsodev.sh down|status|logscatches the new container, anddev.sh up serve-staticworks.infra/README.md— file row, workflow snippet, cheat-sheet row, and a service-endpoint row with thenx build … -c=productionprerequisite called out.Workflow
Decision worth flagging
Used Caddy rather than nginx or Traefik. Reason: minimal Caddyfile, single binary, no daemon config drift, sensible defaults (TLS off explicitly for local-only). Same family of choice as the rest of
infra/local/— small, single-purpose images.redirin a Caddyfile is ambiguous when the first arg starts with/: Caddy reads it as a path matcher rather than a redirect target. Usingredir * /fr/ 302(explicit*matcher) avoids the gotcha. Documented inline in the Caddyfile via a comment block.What this PR explicitly does NOT do
localhost.nx run portal-shell:serve-static(still used by Lighthouse CI inci:perf).__Host-portal_localecookie or honour it for the smart redirect. Cookie handling needs the BFF route (ADR-0019 future PR).Verified locally
GET / -H 'Accept-Language: fr'/fr/GET / -H 'Accept-Language: en'/en/GET /unknown/fr/GET /fr/deep/routefr/index.html)GET /fr/favicons/favicon.svg/fr/index.htmlmarkuplang="fr",<base href="/fr/">/en/index.htmlmarkuplang="en",<base href="/en/">Test plan
docker compose -f infra/local/dev.compose.yml --profile serve-static configvalidates clean.dev.sh up serve-staticbrings the container up;dev.sh statuslists it;dev.sh stop serve-staticbrings it down./{other-locale}/, the matching bundle boots, no console errors. (Verifies PR #95 + #96 end-to-end against a prod-faithful proxy.)/fr/accessibilite→ router-level redirect to/fr/accessibility(verifies PR #94 under SPA fallback).Accept-Language: enin browser settings → root URL lands on/en/.