[object Object]

โ† back to Ventura Corridor

iter 85: feature-of-the-day on /today.html โ€” /api/magazine/feature-of-the-day picks deterministic-by-day-of-year feature (id*DOY%count modulo so it shifts daily but stable within the day) requiring editorial>200 chars; /today.html grows '๐Ÿ“œ Feature of the day' card directly above the magazine progress strip showing headline (32px Cormorant italic, click-to-reader-page), subhead, first 320 chars of editorial, pull-quote callout, biz/address/city/category meta strip; auto-hides if no editorial-rich features exist yet

3f4099c9e0517091fae11af6e52dec7fd16a39e9 ยท 2026-05-06 17:01:27 -0700 ยท SteveStudio2

Files touched

Diff

commit 3f4099c9e0517091fae11af6e52dec7fd16a39e9
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date:   Wed May 6 17:01:27 2026 -0700

    iter 85: feature-of-the-day on /today.html โ€” /api/magazine/feature-of-the-day picks deterministic-by-day-of-year feature (id*DOY%count modulo so it shifts daily but stable within the day) requiring editorial>200 chars; /today.html grows '๐Ÿ“œ Feature of the day' card directly above the magazine progress strip showing headline (32px Cormorant italic, click-to-reader-page), subhead, first 320 chars of editorial, pull-quote callout, biz/address/city/category meta strip; auto-hides if no editorial-rich features exist yet
---
 public/today.html   | 29 +++++++++++++++++++++++++++++
 src/server/index.ts | 19 +++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/public/today.html b/public/today.html
index 0d2a6e0..7601541 100644
--- a/public/today.html
+++ b/public/today.html
@@ -144,6 +144,14 @@
   <div id="prio-strip" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:8px"></div>
 </section>
 
+<section id="fotd-section" style="display:none;padding:24px 32px;border-bottom:1px solid var(--rule);background:linear-gradient(135deg,rgba(212,182,131,0.06),transparent 70%)">
+  <div style="display:flex;justify-content:space-between;align-items:baseline;flex-wrap:wrap;gap:10px">
+    <h3 style="font-family:var(--serif);font-style:italic;font-weight:400;font-size:22px;color:var(--metal-glow);margin:0">๐Ÿ“œ Feature of the day</h3>
+    <a id="fotd-link" href="/magazine.html" style="color:var(--metal);text-decoration:none;font-size:10px;letter-spacing:.18em;text-transform:uppercase;border:1px solid var(--rule);padding:4px 10px">Open โ†—</a>
+  </div>
+  <div id="fotd-body" style="margin-top:14px"></div>
+</section>
+
 <section id="magazine-section" style="padding:20px 32px;border-bottom:1px solid var(--rule);background:rgba(184,153,104,0.04)">
   <div style="display:flex;justify-content:space-between;align-items:baseline;flex-wrap:wrap;gap:10px">
     <h3 style="font-family:var(--serif);font-style:italic;font-weight:400;font-size:22px;color:var(--metal-glow);margin:0">๐Ÿ“– The Corridor <span style="font-size:11px;letter-spacing:.18em;color:var(--ink-mute);margin-left:8px">corridor magazine</span></h3>
@@ -599,6 +607,27 @@ async function loadMagazineStats() {
 }
 loadMagazineStats();
 setInterval(loadMagazineStats, 30_000);
+
+// Feature of the day (iter 85)
+async function loadFOTD() {
+  try {
+    const d = await fetch('/api/magazine/feature-of-the-day').then(r => r.json());
+    const f = d.feature;
+    if (!f) return;
+    document.getElementById('fotd-section').style.display = 'block';
+    document.getElementById('fotd-link').href = '/magazine/' + f.id;
+    document.getElementById('fotd-body').innerHTML = `
+      <h2 style="font-family:var(--serif);font-style:italic;font-weight:400;font-size:32px;line-height:1.05;color:var(--ink);margin:0 0 6px">
+        <a href="/magazine/${f.id}" style="color:inherit;text-decoration:none">${escHtml(f.headline || f.biz_name)}</a>
+      </h2>
+      <div style="font-family:var(--serif);font-style:italic;color:var(--ink-mute);font-size:15px;margin-bottom:14px">${escHtml(f.subhead || '')}</div>
+      <p style="font-family:var(--serif);font-size:15px;line-height:1.55;color:var(--ink);margin:0 0 12px;max-width:720px">${escHtml((f.editorial || '').slice(0, 320))}โ€ฆ</p>
+      ${f.pull_quote ? `<div style="font-family:var(--serif);font-style:italic;color:var(--metal-glow);font-size:18px;border-left:2px solid var(--metal);padding-left:14px;margin:12px 0">"${escHtml(f.pull_quote)}"</div>` : ''}
+      <div style="font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-mute);margin-top:10px">${escHtml(f.biz_name)}${f.biz_address ? ' ยท ' + escHtml(f.biz_address) : ''}${f.city ? ' ยท ' + escHtml(f.city) : ''} ยท ${escHtml(f.category_tag || '')}</div>
+    `;
+  } catch {}
+}
+loadFOTD();
 </script>
 </body>
 </html>
diff --git a/src/server/index.ts b/src/server/index.ts
index 4c6e703..e647a50 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1745,6 +1745,25 @@ app.get('/api/data-freshness', async (_req, res) => {
   }
 });
 
+// Stable per-day feature pick: use day-of-year as seed so it's deterministic for "today"
+app.get('/api/magazine/feature-of-the-day', async (_req, res) => {
+  try {
+    const r = await query(`
+      SELECT mf.id, mf.headline, mf.subhead, mf.editorial, mf.pull_quote, mf.category_tag,
+             b.name AS biz_name, b.address AS biz_address, b.city
+      FROM magazine_features mf
+      JOIN businesses b ON b.id = mf.business_id
+      WHERE mf.editorial IS NOT NULL AND length(mf.editorial) > 200
+      ORDER BY (mf.id * (EXTRACT(DOY FROM CURRENT_DATE)::int + 1)) % (SELECT GREATEST(count(*), 1) FROM magazine_features)
+      LIMIT 1
+    `);
+    if (r.rowCount === 0) return res.json({ feature: null });
+    res.json({ feature: r.rows[0] });
+  } catch (e: any) {
+    res.status(500).json({ error: e.message });
+  }
+});
+
 app.get('/api/magazine/scoreboard', async (_req, res) => {
   try {
     const [topViewed, hotVerticals, latest, longest, sponsors] = await Promise.all([

โ† e460f06 iter 83+84: magazine watchdog launchd + scoreboard wall โ€” sr  ยท  back to Ventura Corridor  ยท  iter 86: nav surfacing for /issue + /scoreboard โ€” adds links c666532 โ†’