# phasefinal-web The Phase Final, Inc. corporate site — nine static pages on **Cloudflare Pages** (project `phasefinal`, account `vh@phasefinal`, `phasefinal.pages.dev`), at `www.phasefinal.com` and `phasefinal.com`. Moved off ana-docker 2026-10-04 (Prime); the nginx container there was retired (`/opt/docker/{compose,conf}/phasefinal-web.retired-20261004`). `conf/site/` is the deployed tree, including `_headers` (the response headers nginx used to set) and `404.html` (without it Pages serves the home page for every unknown path). Built from the design brief at `docs/design/` (boothed 2026-08-29); the markup and CSS came from a Claude Design session and are checked in verbatim under `conf/site/` apart from the two post-export steps below. ## Two steps every fresh export needs The design tool ships the site with **no font binaries** and the `@font-face` block **commented out**, deliberately, to honour the brief's zero-external- requests rule. Both must be undone on import: 1. Drop the four woff2 files into `conf/site/fonts/` (Space Grotesk variable, IBM Plex Sans variable, IBM Plex Mono 400 + 600 — all SIL OFL, self-hosted, no CDN). 2. Uncomment the four `@font-face` rules at the top of `conf/site/style.css`. Without these the page silently falls back to system fonts and looks wrong rather than broken, which is the failure mode you won't notice. ## Deploy ```bash stacks/phasefinal-web/deploy-pages.sh # conf/site → Pages production (branch main) ``` Uses the account token `infra-ops-pages` (vault `nh3-dev/.config/cloudflare/infra-ops-pages-token`). Check the result on the per-deploy preview URL wrangler prints before trusting the custom domains. ## DNS and redirects `www.phasefinal.com` and `phasefinal.com` → CNAME `phasefinal.pages.dev`, Cloudflare-proxied (both are Pages custom domains). Cloudflare-proxied is also what provides the email-address obfuscation the contact block relies on. **The apex 301s to www through a zone Redirect Rule** (`http_request_dynamic_redirect` entrypoint, path and query kept), since Pages `_redirects` cannot redirect between hostnames. Traefik did this before the move. ## Lesson from the ana-docker era (2026-08-29) Traefik silently skips containers Docker reports as unhealthy: no error, no router. The first deploy's healthcheck used `http://localhost/`, which is `::1` in `nginx:alpine` while nginx listened on IPv4 only. Use `127.0.0.1` in healthchecks for IPv4-only listeners. ## Content constraints The copy is governed by hard legal and voice constraints — client naming rules, the never-"military"/"weapons" phrasing rule, no named individuals. **Read the design brief before editing any text.** Edits are made surgically in `conf/site/index.html`; there is no CMS and there will not be one. ## Structure and design rules (cleanup, 2026-09-28) - Every page carries the same site header (wordmark + nav), a real `