[object Object]

← back to Ventura Corridor

iter 133: 404 page now suggests a random published feature

97c9f085007b118fdd3d6832181cf4747857921b · 2026-05-06 18:53:15 -0700 · SteveStudio2

Files touched

Diff

commit 97c9f085007b118fdd3d6832181cf4747857921b
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Wed May 6 18:53:15 2026 -0700

    iter 133: 404 page now suggests a random published feature
---
 src/server/index.ts | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/server/index.ts b/src/server/index.ts
index d508c25..a0130eb 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -3822,9 +3822,27 @@ app.use('/screenshots', express.static(path.resolve(__dirname, '../../data/scree
 // ─── Static viewer ─────────────────────────────────────────────────────
 app.use('/', express.static(path.resolve(__dirname, '../../public')));
 
-// Friendly 404 — magazine-flavored, suggests likely routes
-app.use((req, res) => {
+// Friendly 404 — magazine-flavored, suggests likely routes + a "lottery" pick
+app.use(async (req, res) => {
   if (req.accepts('html')) {
+    const escapeHtml = (s: any) => String(s ?? '').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]!));
+    let lottery: { id: number; headline: string; subhead: string; biz: string } | null = null;
+    try {
+      const r = await query(
+        `SELECT mf.id, mf.headline, mf.subhead, b.name AS biz
+         FROM magazine_features mf JOIN businesses b ON b.id = mf.business_id
+         WHERE mf.status = 'published' AND length(mf.editorial) > 240
+         ORDER BY random() LIMIT 1`
+      );
+      if (r.rowCount) lottery = r.rows[0];
+    } catch {}
+    const lotteryHtml = lottery ? `
+  <div style="margin-top:48px;padding:28px 24px;border-top:1px solid #d8cdb8;border-bottom:1px solid #d8cdb8;background:rgba(184,153,104,0.05);text-align:left">
+    <div class="kicker" style="text-align:center;margin-bottom:14px">A feature you may not have read</div>
+    <div style="font-family:'Cormorant Garamond',serif;font-style:italic;font-weight:500;font-size:32px;line-height:1.05;color:#1a1815;margin-bottom:8px"><a href="/magazine/${lottery.id}" style="color:inherit;text-decoration:none;border-bottom:1px solid transparent" onmouseover="this.style.borderColor='#8a6d3b'" onmouseout="this.style.borderColor='transparent'">${escapeHtml(lottery.headline)}</a></div>
+    <div style="font-family:'Cormorant Garamond',serif;font-style:italic;color:#6e6356;font-size:15px;line-height:1.4;margin-bottom:6px">${escapeHtml(lottery.subhead || '')}</div>
+    <div style="font-size:9px;letter-spacing:.32em;text-transform:uppercase;color:#8a6d3b">${escapeHtml(lottery.biz)}</div>
+  </div>` : '';
     res.status(404).type('html').send(`<!doctype html><html><head><meta charset="utf-8">
 <title>Not in this issue · The Corridor</title>
 <style>
@@ -3853,6 +3871,7 @@ nav a:hover{color:#6a3a1a;border-color:#6a3a1a}
     <a href="/words">Words</a>
     <a href="/rate-card.html">Rates</a>
   </nav>
+  ${lotteryHtml}
 </div>
 </body></html>`);
   } else {

← 030b0b1 iter 131-132: /feedback.html admin viewer + today.html unrea  ·  back to Ventura Corridor  ·  iter 134: /api/magazine/today unified payload — feature + ca f40d96e →