www.pcbjam.com was the last piece of the stack on Vercel. It is now a
Cloudflare Pages project (pcbjam-site) deployed by deploy-site.yml on
every push to main touching site/** — content must not wait for a
release tag.
The Astro adapter is gone entirely: the build is pure static and the one
dynamic route, /api/waitlist, is a Pages Function. Going adapter-free
(rather than swapping in @astrojs/cloudflare, which has dropped Pages
support and only targets Workers) removes three problems at once — no
Astro/adapter major-version coupling, Footer.astro's build-time execSync
keeps working because prerendering stays in Node, and image optimisation
stays plain build-time sharp with no Cloudflare Images binding.
Verified against a real Pages runtime (wrangler pages dev): 21/21 parity
probes pass, versus 19/21 on live Vercel. The scripted runbook is in
deploy/site/ — every mutating step is dry-run by default.
Four behaviour differences were found by measurement and are handled here:
- The blog post's COOP/COEP was already broken in production. vercel.json
scoped the headers to the bare URL, but the page's own canonical is the
trailing-slash form, which served 200 with no isolation headers — so
search arrivals lost SharedArrayBuffer and the embedded Gerber viewer
degraded. public/_headers covers both forms.
- Pages answers unknown URLs with the homepage at HTTP 200 when the
output has no 404.html — a soft-404 that invites indexing junk URLs as
the homepage. Hence src/pages/404.astro.
- Vercel's edge refused cross-site form POSTs ("Cross-site POST form
submissions are forbidden"); Pages does not, and a cross-site <form>
submit needs no CORS permission to be sent, so the allowlist cannot
stop it. The Function reproduces the guard; JSON posts stay exempt as
that is demo.pcbjam.com's allowlisted path.
- Cache-Control: immutable on /_astro/* came from the Vercel adapter's
generated route config, so it is now an explicit _headers rule.
Secrets move to `wrangler pages secret put --project-name pcbjam-site`
(RESEND_API_KEY, RESEND_SEGMENT_ID, WAITLIST_FROM_EMAIL);
WAITLIST_ALLOWED_ORIGINS stays unset so the allowlist stays in code.
Local dev reads .dev.vars, now gitignored — the root repo's **/.dev.vars
does not cover a nested git repo.
privacy.md and cookies.md named Vercel as a GDPR Art. 28 processor; those
mentions are removed and the existing Cloudflare entry widened to cover
website hosting.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LAmkjM7okPdScp9XLW1JVr
35 lines
1.6 KiB
Text
35 lines
1.6 KiB
Text
# Cloudflare Pages response headers for www.pcbjam.com.
|
|
# Copied verbatim from public/ into dist/ by the Astro build. Replaces the
|
|
# `headers` block of the old vercel.json.
|
|
#
|
|
# Cross-origin isolation is required for the embedded KiCad Gerber viewer
|
|
# (SharedArrayBuffer + pthreads). The big WASM blobs it pulls are cross-origin on
|
|
# cdn.pcbjam.com and satisfy COEP via their own CORP/ACAO headers, set by a
|
|
# Cloudflare Transform Rule on that hostname (see deploy/demo/README.md).
|
|
#
|
|
# DO NOT widen these to `/*`. The landing page deliberately is NOT isolated: a
|
|
# require-corp document cannot load the no-COEP YouTube hero iframe. See the
|
|
# comment in src/sections/GerberDemoSection.astro.
|
|
#
|
|
# Both URL forms of the blog post are listed on purpose. Pages serves the
|
|
# trailing-slash form at 200 and 308s the bare form to it, so an exact-match rule
|
|
# alone would attach these headers to the redirect and not to the document —
|
|
# which is precisely the bug this file inherited from vercel.json.
|
|
|
|
# Content-hashed build output: safe to cache forever. This used to come from the
|
|
# Vercel adapter's generated route config; with no adapter, nothing sets it unless
|
|
# we do.
|
|
/_astro/*
|
|
Cache-Control: public, max-age=31536000, immutable
|
|
|
|
/blog/porting-kicad-graphics-to-webgl-in-2026
|
|
Cross-Origin-Opener-Policy: same-origin
|
|
Cross-Origin-Embedder-Policy: require-corp
|
|
|
|
/blog/porting-kicad-graphics-to-webgl-in-2026/*
|
|
Cross-Origin-Opener-Policy: same-origin
|
|
Cross-Origin-Embedder-Policy: require-corp
|
|
|
|
/gerber-demo/*
|
|
Cross-Origin-Opener-Policy: same-origin
|
|
Cross-Origin-Embedder-Policy: require-corp
|