← back to Blockprintedwallpaper
add: clean-URL routes for /history /vocabulary /sourcing /care /trade + 404 guard
da1fc9a603896a581df86471ddb55bfdfffdbaaa · 2026-05-25 20:51:14 -0700 · SteveStudio2
Every page template's local nav links to extension-less URLs (/history,
/vocabulary, etc.) but Express's static middleware does not auto-strip
.html, so cross-page nav was 404-ing. Mount one explicit route per page.
Also add a terminal 404 middleware — JSON for /api/* probes, friendly
HTML "return home" for everything else. Stops drive-by URL probes from
showing a blank Cannot GET line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit da1fc9a603896a581df86471ddb55bfdfffdbaaa
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Mon May 25 20:51:14 2026 -0700
add: clean-URL routes for /history /vocabulary /sourcing /care /trade + 404 guard
Every page template's local nav links to extension-less URLs (/history,
/vocabulary, etc.) but Express's static middleware does not auto-strip
.html, so cross-page nav was 404-ing. Mount one explicit route per page.
Also add a terminal 404 middleware — JSON for /api/* probes, friendly
HTML "return home" for everything else. Stops drive-by URL probes from
showing a blank Cannot GET line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
server.js | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/server.js b/server.js
index f46bb51..4acf837 100644
--- a/server.js
+++ b/server.js
@@ -153,6 +153,14 @@ app.get('/api/health', (req, res) => res.json({ status: 'ok', count: PRODUCTS_NI
// /about — the brand history page (history.html). Nav links to /about; serve it here.
app.get('/about', (req, res) => res.sendFile(path.join(__dirname, 'public', 'history.html')));
+// Clean-URL routes for extension-less nav links present across all page
+// templates (history/vocabulary/sourcing/care/trade). Without these,
+// express.static would not auto-strip .html and every cross-page nav 404'd.
+const CLEAN_PAGES = ['history', 'vocabulary', 'sourcing', 'care', 'trade'];
+for (const slug of CLEAN_PAGES) {
+ app.get('/' + slug, (req, res) => res.sendFile(path.join(__dirname, 'public', slug + '.html')));
+}
+
app.get('/sample/:handle', (req, res) => {
const p = PRODUCTS_NICHE.find(x => x.handle === req.params.handle || x.sku === req.params.handle);
if (!p) return res.status(404).send('Not found');
@@ -178,6 +186,22 @@ ${urls.map(u => ` <url><loc>https://blockprintedwallpaper.com${u}</loc><changef
// Admin catalog CRUD — /admin/catalog (basic-auth) + /api/admin/* REST.
if (catalog) catalog.mount(app, { siteSlug: SITE_SLUG, rails: SITE_RAILS });
+// 404 guard — JSON for /api/*, friendly HTML redirect to home for everything
+// else. Keeps drive-by URL probes from getting a stack trace or blank page.
+app.use((req, res) => {
+ if (req.path.startsWith('/api/')) {
+ return res.status(404).json({ error: 'not_found', path: req.path });
+ }
+ res.status(404).type('html').send(
+ '<!doctype html><meta charset=utf-8><title>Not found · blockprintedwallpaper</title>' +
+ '<meta http-equiv="refresh" content="0; url=/">' +
+ '<style>body{font-family:Inter,system-ui,sans-serif;background:#FAFAFA;color:#000;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;text-align:center}a{color:#b85c40;text-decoration:none;border-bottom:1px solid #b85c40;padding-bottom:2px}</style>' +
+ '<main><p style="font-size:11px;letter-spacing:0.32em;text-transform:uppercase;font-weight:700;color:#8B7866;margin-bottom:16px">404</p>' +
+ '<p style="font-size:18px;margin-bottom:24px">That page isn’t here.</p>' +
+ '<a href="/">Return home</a></main>'
+ );
+});
+
// Load the catalog. When admin is enabled, prefer dw_unified; else static JSON.
(async () => {
let loaded = false;
← 9ef46b6 fix: add noreferrer to footer Facebook target=_blank
·
back to Blockprintedwallpaper
·
redact vendor names from customer-facing /api (close fleet l 36416e5 →