From c82eca38faca93c5486ae456ee8c2c7a5568ea2f Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 15 Apr 2026 17:19:41 -0400 Subject: [PATCH] fix(server): add styled 404 page + stop SPA fallback serving stale HTML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add app.notFound() handler with themed 404 page instead of Hono's plain "404 Not Found". Restrict canvas.html SPA fallback to /rspace sub-paths only — was serving index.html for all unmatched routes, causing stale "Activated" page to appear on navigation errors. Co-Authored-By: Claude Opus 4.6 --- server/index.ts | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/server/index.ts b/server/index.ts index 6a66099f..2a8708a0 100644 --- a/server/index.ts +++ b/server/index.ts @@ -3664,6 +3664,37 @@ app.get("/:space", (c) => { return c.redirect("/", 302); }); +// ── Custom 404 page ── +app.notFound((c) => { + const path = c.req.path; + // API routes: return JSON 404 + if (path.startsWith("/api/") || c.req.header("accept")?.includes("application/json")) { + return c.json({ error: "Not found" }, 404); + } + return c.html(` + + + +Page Not Found | rSpace + + +
+

404

+

This page doesn't exist — it may have moved or the URL might be wrong.

+Back to rSpace +

${path}

+
`, 404); +}); + // ── WebSocket types ── interface WSData { communitySlug: string; @@ -4343,11 +4374,11 @@ const server = Bun.serve({ if (shellResponse.status === 200) return shellResponse; } - // Non-module path — try canvas/index SPA fallback - const canvasHtml = await serveStatic("canvas.html"); - if (canvasHtml) return canvasHtml; - const indexHtml = await serveStatic("index.html"); - if (indexHtml) return indexHtml; + // Canvas SPA fallback (only for /rspace sub-paths, not general 404s) + if (parts[0] === "rspace" || (subdomain && parts[0] === "rspace")) { + const canvasHtml = await serveStatic("canvas.html"); + if (canvasHtml) return canvasHtml; + } } }