Communitygithub.com

vanilla-site-cloudflare

Build and ship a no-framework static site (HTML/CSS/JS vanilla) on Cloudflare Pages with GitHub auto-deploy, cache-busting, auto-reload-on-deploy, and security headers. Use when building or deploying a static/lightly-dynamic site, setting up the deploy flow, fixing "no se ve / stale cache" problems, deciding framework vs vanilla, or when the user mentions Cloudflare Pages, cache-bust, `_headers`, CSP, or a forced refresh. Includes the proven deploy ritual and reusable scripts.

What is vanilla-site-cloudflare?

vanilla-site-cloudflare is a Claude Code agent skill that build and ship a no-framework static site (HTML/CSS/JS vanilla) on Cloudflare Pages with GitHub auto-deploy, cache-busting, auto-reload-on-deploy, and security headers. Use when building or deploying a static/lightly-dynamic site, setting up the deploy flow, fixing "no se ve / stale cache" problems, deciding framework vs vanilla, or when the user mentions Cloudflare Pages, cache-bust, `_headers`, CSP, or a forced refresh. Includes the proven deploy ritual and reusable scripts.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Mreboredo/skills-cobros-argentina/tree/HEAD/vanilla-site-cloudflare

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Vanilla static site on Cloudflare Pages

No build step. Edit files → push to main → Cloudflare Pages auto-deploys. Fast, cheap, and you never fight a toolchain.

Why vanilla (decision rationale)

  • Zero build/CI churn; a 2-line copy fix is a 30-second deploy.
  • No framework lock-in or rewrite tax. "Add, don't rewrite" is the rule.
  • The whole site is greppable, debuggable, and obvious.
  • Trade-off accepted: more manual DOM code. Worth it at small/medium scale.

Repo + deploy

  • One GitHub repo → Cloudflare Pages project, auto-deploy on push to main.
  • Pages serves the repo root. Pretty URLs: /mi-cuenta.html is served at /mi-cuenta.
  • Functions (serverless) live in /functions (see supabase-backend).

The deploy ritual (do this EVERY deploy)

  1. Edit the files.
  2. Verify JS compiles — never push broken inline JS. Extract inline <script> blocks and run vm.compileFunction on each; node --check for .js/.cjs. See reference/verify-inline.cjs.
  3. Cache-bust the assets: node .claude/cache-bust.cjs — stamps every assets/**/*.css|js reference in the HTML with ?v=<git-short-hash> and writes version.json. See reference/cache-bust.cjs.
  4. Bump the version stamp (single source of truth in one JS file, shown subtly in the footer) and log it. See project-continuity for the versioning scheme.
  5. Commit (descriptive, in the project's language) with the co-author trailer, push to main.
  6. Verify live: curl the deployed asset and confirm the new version stamp + that version.json equals the asset ?v= (they must match or the auto-reloader loops). Cloudflare bot-protection blocks plain crawlers → use a browser User-Agent.

.claude/ is typically gitignored, so the cache-bust/verify scripts stay local (they run at build time on your machine, not in the repo).

Cache-busting + auto-reload (kills the "no se ve" telephone game)

Two layers, both in reference/:

  1. cache-bust.cjs — re-stamps ?v=<git hash> on all asset refs each deploy so browsers re-fetch changed CSS/JS, AND writes version.json = {"v":"<hash>"}.
  2. Auto-reloader (reference/auto-reload.js) — a tiny script included on every page that reads its own loaded ?v=, polls /version.json (served no-store), and when a new deploy is detected: reloads on tab-return (safe moment), shows a one-tap "Actualizar" banner while you're looking, and never interrupts mid-typing (window.__noAutoReload opt-out for exam/checkout flows). Bootstrap caveat: the first time, users hard-refresh once to load the reloader; from then on it's automatic.

Serve the marker fresh via _headers:

/version.json
  Cache-Control: no-store, max-age=0

Security headers (_headers at repo root)

Always set: Content-Security-Policy (lock script-src/frame-src/connect-src to the exact CDNs + your Supabase URL + wss for realtime), X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, Permissions-Policy, Strict-Transport-Security. Gotcha lived: embedding a video iframe needs the player domain in frame-src or the browser silently blocks it.

Reusable CSS conventions

  • Token-based theming with CSS variables; a data-theme="dark" remap + a shared localStorage key so the theme syncs across pages/tabs.
  • Dark mode: contrast-passing is not enough — you also need visible layer hierarchy (bg < surface < card) with light steps + shadow, or it reads as flat.
  • Never hardcode white/colors; use tokens so the theme responds.
  • Don't break global .btn/.btn-primary; override in scope.

Files in this skill

  • reference/cache-bust.cjs — the asset-stamper + version.json writer.
  • reference/auto-reload.js — the deploy auto-reloader (drop into a globally-loaded JS file).
  • reference/verify-inline.cjs — compile-check inline <script> blocks before deploy.
  • reference/headers-example — a starter _headers.

Related Skills