sandbox.gf.cx — SHIPPED 2026-05-24 · canonical subdomain template + scaffold
DARE.CO.UK · PARKED SKETCH · 2026-05-26
Mirrored from ~/.claude/.../memory/parked_sketch_sandbox_gfcx_subdomain_template.md. This is a design sketch parked for future build — read for context, not as a current deliverable.
SHIPPED. The scaffold script ~/bin/gfcx_subdomain_new.py + templates at ~/Code/toolkit/subdomain-scaffold/templates/ generate a new gf.cx subdomain in one command. Bakes in declarative landing, context-aware 404, cards.css + media.css imports, stamps, micro-gestures, _redirects + wrangler.toml. First dogfood instance: sandbox.gf.cx (deployed 2026-05-24, custom-domain bind pending).
STATUS: SHIPPED 2026-05-24
Built and deployed:
- ~/Code/toolkit/subdomain-scaffold/templates/ — 5 template files (index.html, 404.html, wrangler.toml, _redirects, README.md) with {{var}} placeholders
- ~/bin/gfcx_subdomain_new.py — orchestrator script. Usage: gfcx_subdomain_new.py <name> [--title ...] [--kicker ...] [--description ...] [--lede ...] [--dry-run]
- Dogfood: ~/Code/sandbox.gf.cx/ (generated 2026-05-24) → CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Pages project sandbox-gf-cx (created via wrangler pages project create) → preview live at https://sandbox-gf-cx.pages.dev/
- Custom domain sandbox.gf.cx bind: PENDING — needs Cloudflare dashboard step (Pages → sandbox-gf-cx → Custom domains → add sandbox.gf.cx)
What got baked into the scaffold:
- Declarative landing — “what’s here / what’s not / where to look instead” structure (per feedback_declarative_pages_for_infra_subdomains.md)
- Context-aware 404 — JS surfaces the attempted path + suggests parent-path siblings + portfolio cross-links
- Cards primitive import — <link href="https://assets.gf.cx/cards/cards.css"> on every generated index
- Media-sizing primitive import — same for /media/media.css
- Stamps — HTML comment <!-- generated by gfcx_subdomain_new.py vX.Y.Z @ <date> --> + footer with regenerate notes
- Portfolio palette — --bg / --ink / --accent / --line / --sans / --serif / --mono defined inline (overridable)
- Hover gesture — anchor borders shift to accent on hover (no transform, per Dan’s prior nit)
- _redirects — CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Pages-style redirect map scaffold with example syntax
- wrangler.toml — CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Pages config with project name pre-stamped + deploy command in comments
- README.md — what’s here + deploy steps + custom-domain bind instructions + pattern-library cross-references
To spin up a new subdomain now:
~/bin/gfcx_subdomain_new.py io --title "io" --kicker "public-access portals · gf.cx"
cd ~/Code/io.gf.cx
env -u CLOUDFLARE_API_TOKEN npx wrangler pages project create io-gf-cx --production-branch=main
env -u CLOUDFLARE_API_TOKEN npx wrangler pages deploy . --project-name=io-gf-cx --branch=main --commit-dirty=true
# Then CF dashboard → Pages → io-gf-cx → Custom domains → add io.gf.cx
CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Pages project create + custom-domain bind are still manual (CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF API tokens for those operations have the quirk documented in feedback_cf_token_config_rules_api_quirk.md).
Dan 2026-05-23: “https://payload.gf.cx/evernote/ gives a 404 — the entire payload.gf.cx needs a catch-all for 404, that’s similar to pa.gf.cx, are you lost? you were searching for
The motivating gap
Today each subdomain accumulates affordances ad-hoc:
- pa.gf.cx has a 404 page, has a landing, has thumbnail pipeline on cards
- payload.gf.cx got a landing in this session, has no 404 catch-all (hit at /evernote/)
- assets.gf.cx has a landing, has a 404.html
- io.gf.cx is still on Notion; nothing wired
When a new subdomain stands up, someone has to remember the full affordance list. Easy to ship without one or two. sandbox.gf.cx becomes the reference implementation that has ALL of them, so future subdomains clone from it.
Affordance checklist (the template content)
| Affordance | What it does | Lives in |
|---|---|---|
Declarative / landing |
Explains what the subdomain is, what lives here, what doesn’t, where to look instead | index.html |
| 404 catch-all | “Are you lost? You were searching for <path> — try X or Y” with friendly tone, links back to landing |
404.html + project config (CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Pages: automatic; R2-custom-domain: needs Worker or transform) |
| media.css import | <link rel="stylesheet" href="https://assets.gf.cx/media/media.css"> in any page that embeds video/img |
every HTML file |
| Thumbnail pipeline on cards | Any card-grid surface that links to another URL gets an OG-image-style thumbnail (the dare.co.uk pattern) | thumbnailer.py / pa thumbnail service |
| Redirect rules scaffolding | A reusable CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Transform Rule pattern: /index → /, trailing-slash normalisation, www. → apex, etc. |
CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Rules (deployed via API) |
| Grayscale-thumb hover | Card thumbnails default grayscale + restore color on hover (feedback_grayscale_thumb_hover_pattern.md) |
shared CSS (candidate for assets.gf.cx/cards/cards.css primitive) |
| Robots/sitemap | robots.txt + sitemap.xml (auto-generated or hand) |
project root |
| Favicon + apple-touch-icon | Tiny set consistent with portfolio brand | project root |
| CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Access posture | Public OR Access-gated declaration in a .cf-access-policy.md file (operator-facing) |
project root |
| Last-touched date | Footer freshness stamp per feedback_last_touched_freshness_pattern.md |
every HTML file |
Repo shape
xlab-co/toolkit/subdomain-template/
README.md — what this is, how to clone
index.html — declarative landing skeleton
404.html — friendly catch-all
robots.txt
sitemap.xml.tmpl
wrangler.toml — CF Pages project config
scripts/
deploy.sh — wrangler pages deploy
apply-rules.sh — fires CF API to deploy Transform Rules
.cf-access-policy.md.tmpl
README-affordances.md — the checklist above as a runbook
First instance: sandbox.gf.cx
Stand it up as the test bed. Build the template by extracting affordances from pa.gf.cx (most mature), then verify they all work on sandbox.gf.cx before cloning to fix payload.gf.cx’s missing 404 catch-all and seeding io.gf.cx.
What this also fixes
- payload.gf.cx 404 on
/evernote/— once the template ships, payload gets the same 404.html catch-all routing (probably via a Worker now in front of R2, since R2-custom-domain can’t serve a 404 page from a missing key). - Future subdomains — io.gf.cx, ask-opus.gf.cx, new ones — clone the template instead of inventing.
Cross-references
feedback_declarative_pages_for_infra_subdomains.md— the landing rule (template formalises it)feedback_payload_gfcx_public_only_policy.md— sibling subdomain currently missing 404 catch-allfeedback_grayscale_thumb_hover_pattern.md— one affordance to fold infeedback_last_touched_freshness_pattern.md— another affordancefeedback_xlab_co_toolkit_web_assets_home.md— where the template livesproject_io_gfcx_public_access_subdomain.md— first consumer once template exists
Resume conditions
- Dan asks to start building the template
- A new subdomain is about to stand up (io.gf.cx, others) and would benefit from cloning
- A 404 incident on payload.gf.cx prompts a hot-fix (build template’s 404 path immediately, retrofit payload)