Compare commits
2 Commits
7214599f5a
...
9f258702a1
| Author | SHA1 | Date |
|---|---|---|
|
|
9f258702a1 | |
|
|
c82eca38fa |
|
|
@ -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(`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Page Not Found | rSpace</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:system-ui,-apple-system,sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#e2e8f0}
|
||||
.c{max-width:480px;text-align:center;padding:2rem}
|
||||
h1{font-size:4rem;margin-bottom:0.5rem;background:linear-gradient(135deg,#5eead4,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
|
||||
p{color:#94a3b8;line-height:1.6;margin-bottom:1.5rem}
|
||||
a{color:#5eead4;text-decoration:none;padding:0.5rem 1.5rem;border:1px solid #5eead4;border-radius:8px;transition:all 0.2s}
|
||||
a:hover{background:#5eead4;color:#0f172a}
|
||||
.sub{font-size:0.85rem;color:#475569;margin-top:2rem}
|
||||
</style>
|
||||
</head>
|
||||
<body><div class="c">
|
||||
<h1>404</h1>
|
||||
<p>This page doesn't exist — it may have moved or the URL might be wrong.</p>
|
||||
<a href="/">Back to rSpace</a>
|
||||
<p class="sub">${path}</p>
|
||||
</div></body></html>`, 404);
|
||||
});
|
||||
|
||||
// ── WebSocket types ──
|
||||
interface WSData {
|
||||
communitySlug: string;
|
||||
|
|
@ -4343,11 +4374,11 @@ const server = Bun.serve<WSData>({
|
|||
if (shellResponse.status === 200) return shellResponse;
|
||||
}
|
||||
|
||||
// Non-module path — try canvas/index SPA fallback
|
||||
// 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;
|
||||
const indexHtml = await serveStatic("index.html");
|
||||
if (indexHtml) return indexHtml;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue