chess-pressure/dev-server.js
Michael Pilosov cf24009e31 feat: opt-in PWA/offline behind ENABLE_CHESS_PWA flag; add cache-version bump
- sw.js + manifest.json: cache-first service worker for instant repeat-visit
  loads and full offline use. Registered only when window.CHESS_PWA is true.
- Disabled by default: an active SW serves returning visitors from cache, so
  they'd stop hitting the server and disappear from the Fly logs. Enable at
  build time with --build-arg ENABLE_CHESS_PWA=1 (Dockerfile flips the flag);
  ENABLE_CHESS_PWA=1 make dev does the same locally.
- scripts/bump_version.sh + 'make bump': bump the asset cache version across
  index.html (?v=N) and sw.js (CACHE) in sync. Required before deploy so the
  service worker / browser cache pick up changed assets. Bumped v25 -> v26.
- README: document cache versioning + PWA flag.
2026-06-25 20:47:19 +00:00

38 lines
1.7 KiB
JavaScript

// Lightweight static dev server for chess-pressure.
// Serves src/chess_pressure/static/ at the root, matching the production
// static-web-server layout. Files are read fresh per request, so editing a
// JS/CSS/HTML file and refreshing the browser picks up changes immediately.
//
// bun run dev-server.js # serves http://0.0.0.0:8888
// PORT=9000 bun run dev-server.js
const ROOT = new URL("./src/chess_pressure/static/", import.meta.url).pathname;
const PORT = Number(process.env.PORT || 8888);
const PWA = process.env.ENABLE_CHESS_PWA === "1"; // mirror the Docker build flag
Bun.serve({
port: PORT,
hostname: "0.0.0.0",
async fetch(req) {
let pathname = decodeURIComponent(new URL(req.url).pathname);
if (pathname === "/" || pathname === "") pathname = "/index.html";
// Strip leading slashes and neutralize any ".." path traversal.
const rel = pathname.replace(/^\/+/, "").replace(/\.\.(\/|\\|$)/g, "");
const file = Bun.file(ROOT + rel);
if (!(await file.exists())) return new Response("Not found", { status: 404 });
const headers = { "Cache-Control": "no-cache" };
// Flip the PWA flag in index.html on the fly so `ENABLE_CHESS_PWA=1 make dev`
// can exercise the service worker without editing source.
if (PWA && rel === "index.html") {
const html = (await file.text()).replace("window.CHESS_PWA = false", "window.CHESS_PWA = true");
return new Response(html, { headers: { ...headers, "Content-Type": "text/html;charset=utf-8" } });
}
return new Response(file, { headers });
},
});
console.log(
`chess-pressure dev server → http://0.0.0.0:${PORT} (serving ${ROOT}) PWA=${PWA ? "on" : "off"}`,
);