Files
CodeWhale Bot cfe4d21075 perf(web): serve one canonical host and a 61%-smaller product screenshot
Two things the site was paying for on every visit.

**www served the whole site.** `web/wrangler.jsonc` binds both `codewhale.net`
and `www.codewhale.net` to this worker as custom domains, and nothing
redirected between them — so every page had a second reachable, indexable URL
and the two hosts split whatever authority they earned. `middleware.ts` now
301s `www` to the apex before the locale and static-asset branches, so a
document that moves does not keep pulling subresources from the host it left.
The redirect keeps path and query, leaves the apex, localhost, and preview
hosts alone, and still carries the security headers.

Doing it in middleware rather than moving the route to the existing
`web/redirect` worker is deliberate: reassigning a custom domain between
workers has a window where `www` answers with nothing, and this ships
atomically with the next deploy.

**The LCP element was a 440 KB PNG.** `app/[locale]/page.tsx` marks the product
screenshot `priority`, so it is the largest contentful paint, and it was served
raw — `next/image` is wired up but the Cloudflare transform binding is not
enabled, so nothing resized or re-encoded it. Re-encoded as lossless WebP:

    440,507 -> 172,380 bytes  (-60.9%)

Verified pixel-identical before swapping, not assumed — decoded both and
compared: difference bbox `None`, max channel delta 0 across RGBA. A lossy
q88 encode was 41 KB but showed a max channel delta of 67, which is visible
artifacting on terminal text, so it was rejected.

`docs/public-surface-facts.json` holds the README and website screenshots to
one byte-identical canonical asset, so both move together — `assets/screenshot.webp`
is the same file, and the 19 READMEs and their source stamps follow. That
contract is why this is one commit and not two.

The contract test read dimensions from the PNG IHDR; it now parses the packed
14-bit fields of the lossless VP8L header, and still accepts PNG so the asset
can be swapped back without touching the test.

Enabling the Cloudflare Images binding would let `next/image` negotiate AVIF
and per-viewport widths on top of this, but it needs Images enabled on the
zone, so it is left for a deliberate infra change rather than smuggled in here.

Verified: `npx vitest run` — 31 files, 276 tests passing (5 new middleware
tests, confirmed failing without the redirect); `tsc --noEmit` clean;
`check-readme-translations.py` reports 18 in sync; `prepare-release.sh 0.9.10`
clean.
2026-08-18 19:49:02 -07:00

168 KiB
1562x1256px