# 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) ``` Needs a vaulted Cloudflare token with Account → Cloudflare Pages: Edit (see the script). ⚠ The 2026-10-04 migration used jackdaw's token as a one-off; a dedicated `nh3-dev/.config/cloudflare/infra-ops-pages-token` is pending Prime. 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 no longer 301s to www**: Traefik used to do that, Pages `_redirects` cannot redirect between hostnames, and no vaulted token may create a zone Redirect Rule. Both hostnames serve the site until Prime mints a token with Single Redirect: Edit; then add the rule `phasefinal.com/* → https://www.phasefinal.com/${1}` (301). ## 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 `