← back to AsSeenInMovies
asseeninmovies: branded 404 — was leaking stock Express 'Cannot GET /…' plain-text page. New handler uses htmlShell (theme+nav+footer consistent) with 6 chip-style recovery links (Home/Movies/People/Spotted/Search/🎲 random). /api/* paths get JSON 404 instead of HTML.
56476afe127192acc0738eb8a54a38c56835f1be · 2026-05-12 19:16:15 -0700 · SteveStudio2
Files touched
Diff
commit 56476afe127192acc0738eb8a54a38c56835f1be
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Tue May 12 19:16:15 2026 -0700
asseeninmovies: branded 404 — was leaking stock Express 'Cannot GET /…' plain-text page. New handler uses htmlShell (theme+nav+footer consistent) with 6 chip-style recovery links (Home/Movies/People/Spotted/Search/🎲 random). /api/* paths get JSON 404 instead of HTML.
---
server.js | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/server.js b/server.js
index d7b11a0..ad0c1ca 100644
--- a/server.js
+++ b/server.js
@@ -1684,6 +1684,30 @@ app.get('/robots.txt', (_req, res) => {
res.type('text/plain').send(`User-agent: *\nAllow: /\nDisallow: /spotted/queue\nDisallow: /api/\nSitemap: ${base}/sitemap.xml\n`);
});
+// Branded 404 — was leaking the stock Express "Cannot GET /…" plain-text
+// page. Now uses htmlShell so theme + nav + footer are consistent, plus
+// suggested paths to recover (movies / people / spotted / search / random).
+app.use((req, res) => {
+ if (req.path.startsWith('/api/')) {
+ return res.status(404).json({ error: 'not-found', path: req.path });
+ }
+ const body = `
+ <div style="max-width:600px;margin:80px auto;text-align:center">
+ <h1 class="title" style="font-size:96px;color:var(--gold);margin:0">404</h1>
+ <p class="meta-line" style="margin:8px 0 28px">${esc(req.path)} — page not found</p>
+ <p style="color:var(--ink-soft);margin-bottom:32px">The film, person, or page you were looking for isn't here. A few places to recover:</p>
+ <div style="display:flex;flex-wrap:wrap;gap:10px;justify-content:center">
+ <a class="chip" href="/" style="border-color:var(--gold);color:var(--gold);padding:8px 18px;text-decoration:none">Home</a>
+ <a class="chip" href="/movies" style="border-color:var(--gold);color:var(--gold);padding:8px 18px;text-decoration:none">Movies</a>
+ <a class="chip" href="/people" style="border-color:var(--gold);color:var(--gold);padding:8px 18px;text-decoration:none">People</a>
+ <a class="chip" href="/spotted" style="border-color:var(--gold);color:var(--gold);padding:8px 18px;text-decoration:none">Spotted</a>
+ <a class="chip" href="/search" style="border-color:var(--gold);color:var(--gold);padding:8px 18px;text-decoration:none">Search</a>
+ <a class="chip" href="/random/movie" style="border-color:var(--gold);color:var(--gold);padding:8px 18px;text-decoration:none">🎲 Random movie</a>
+ </div>
+ </div>`;
+ res.status(404).type('html').send(htmlShell('Not Found', body));
+});
+
app.listen(PORT, '127.0.0.1', async () => {
await ensureSchema();
console.log(`asseeninmovies → http://127.0.0.1:${PORT}`);
← b8cbc44 asseeninmovies: GET /random/movie and /random/person — 302 t
·
back to AsSeenInMovies
·
asseeninmovies: /spotted ItemList JSON-LD — each placement e fd70620 →