67 lines
3.6 KiB
Markdown
67 lines
3.6 KiB
Markdown
# 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 `<h1>`, and the same footer outside `<main>`. Change the nav in all nine files at once: the labels are Applications, Systems, Hosting, AI, Engagement, Track record, Contact (+ Privacy in the footer).
|
|
- **The stylesheet link carries a version** (`/style.css?v=<date>`). CSS is cached for an hour (`nginx.conf`), so markup that changes with the CSS must bump it, or new pages meet old styles at the edge.
|
|
- **Anti-slop waivers, operator ruling 2026-09-28:**
|
|
- The hero's full-bleed 3px volt rule is a brand device. The Impeccable detector's `side-tab` rule flags it; that is waived.
|
|
- Space Grotesk is the brand display face. `overused-font` is waived.
|
|
- Everything else must stay clean: 0 other unwaived rows at 1280 and 390, light and dark.
|
|
|