diff --git a/.gitignore b/.gitignore
index 58efa0e7..ecb29795 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,9 @@ mac/dist/
# Marketing site (site/) build artifacts
site/node_modules/
site/dist/
+# `wrangler pages dev site/dist` — used to reproduce Cloudflare Pages' header
+# and not-found behaviour locally — drops its state here.
+.wrangler/
# Dashboard build output — produced by `make dashboard-build`.
# A committed `.gitkeep` keeps dist/ non-empty so `//go:embed all:dist` works
# on a fresh clone (the embed.FS needs at least one entry). The real
diff --git a/site/public/404.html b/site/public/404.html
new file mode 100644
index 00000000..ba33b263
--- /dev/null
+++ b/site/public/404.html
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+ Not found · cix · CodeIndeX
+
+
+
+
+
+
+
+
404
+
Nothing indexed at this path
+
The page you asked for does not exist. If you landed here from a link on the site, it is a bug worth reporting.
+ Back to codeindex.app
+
+
+
diff --git a/site/vite.config.js b/site/vite.config.js
index 494e320c..57b7b040 100644
--- a/site/vite.config.js
+++ b/site/vite.config.js
@@ -12,6 +12,18 @@ const here = dirname(fileURLToPath(import.meta.url));
export default defineConfig({
plugins: [react()],
build: {
+ // Cache generation, bumped to evacuate a poisoned URL. On 2026-08-10 a
+ // deploy window answered requests for /assets/*.js with index.html and a
+ // 200, and public/_headers stamped that HTML with the year-long immutable
+ // Cache-Control meant for hashed bundles — so every browser that hit the
+ // site during the window pinned "HTML that claims to be JavaScript" until
+ // 2027 and rendered a blank page. Content hashes cannot rescue those
+ // clients (the poisoned entry is keyed by the URL, and the URL was right),
+ // so the whole directory moves instead; index.html is served
+ // must-revalidate and picks the new paths up immediately.
+ // public/404.html now makes a missing asset a real 404, which is what
+ // stops this from recurring — bump this only if it somehow happens again.
+ assetsDir: 'assets/g2',
rollupOptions: {
input: {
main: resolve(here, 'index.html'),