← back to Ventura Corridor
iter 113+114: pitch_event_log audit panel on /magazine/:id + feature-of-the-week — reader page now appends a collapsible <details> 'Editorial dossier · N pipeline events' that lists last 10 audit events from pitch_event_log for the underlying business (timestamp · event_type · old → new) in JetBrains Mono with subtle italic footnote ('From the DW outreach pipeline that produces the magazine — every walk, every reply, every status change'); /api/magazine/feature-of-the-week picks deterministic-by-week-of-year (id*WK%count) feature requiring editorial>300 chars + status IN (published, reviewed); /today.html grows '📰 Feature of the week' compact pill below FOTD
0bc6fd66a1ee37a35c99a6e24322b9e9f1a3e80b · 2026-05-06 17:58:26 -0700 · SteveStudio2
Files touched
M public/today.htmlM src/server/index.ts
Diff
commit 0bc6fd66a1ee37a35c99a6e24322b9e9f1a3e80b
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Wed May 6 17:58:26 2026 -0700
iter 113+114: pitch_event_log audit panel on /magazine/:id + feature-of-the-week — reader page now appends a collapsible <details> 'Editorial dossier · N pipeline events' that lists last 10 audit events from pitch_event_log for the underlying business (timestamp · event_type · old → new) in JetBrains Mono with subtle italic footnote ('From the DW outreach pipeline that produces the magazine — every walk, every reply, every status change'); /api/magazine/feature-of-the-week picks deterministic-by-week-of-year (id*WK%count) feature requiring editorial>300 chars + status IN (published, reviewed); /today.html grows '📰 Feature of the week' compact pill below FOTD
---
public/today.html | 23 +++++++++++++++++++++++
src/server/index.ts | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+)
diff --git a/public/today.html b/public/today.html
index 7d972d7..8e916b4 100644
--- a/public/today.html
+++ b/public/today.html
@@ -154,6 +154,14 @@
<div id="fotd-body" style="margin-top:14px"></div>
</section>
+<section id="fotw-section" style="display:none;padding:18px 32px;border-bottom:1px solid var(--rule);background:radial-gradient(ellipse at left, rgba(106,58,26,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:18px;color:var(--accent,#a8763a);margin:0">📰 Feature of the week</h3>
+ <a id="fotw-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:3px 8px">Open ↗</a>
+ </div>
+ <div id="fotw-body" style="margin-top:8px;font-family:var(--serif);font-style:italic;font-size:14px;color:var(--ink-mute);line-height:1.5"></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>
@@ -630,6 +638,21 @@ async function loadFOTD() {
} catch {}
}
loadFOTD();
+
+async function loadFOTW() {
+ try {
+ const d = await fetch('/api/magazine/feature-of-the-week').then(r => r.json());
+ const f = d.feature;
+ if (!f) return;
+ document.getElementById('fotw-section').style.display = 'block';
+ document.getElementById('fotw-link').href = '/magazine/' + f.id;
+ document.getElementById('fotw-body').innerHTML = `
+ <a href="/magazine/${f.id}" style="font-family:var(--serif);font-size:18px;font-style:italic;color:var(--ink);text-decoration:none">${escHtml(f.headline || f.biz_name)}</a>
+ <span style="color:var(--ink-mute);font-size:12px;margin-left:6px">— ${escHtml(f.biz_name)} · ${escHtml(f.category_tag || '')}</span>
+ `;
+ } catch {}
+}
+loadFOTW();
</script>
</body>
</html>
diff --git a/src/server/index.ts b/src/server/index.ts
index 608e765..32526a0 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1778,6 +1778,26 @@ app.get('/api/magazine/stale', async (req, res) => {
}
});
+// Stable per-week pick: rotates weekly, prefers published features for editorial polish
+app.get('/api/magazine/feature-of-the-week', 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) > 300
+ AND mf.status IN ('published', 'reviewed')
+ ORDER BY (mf.id * (EXTRACT(WEEK FROM CURRENT_DATE)::int + 7)) % (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/feature-of-the-day', async (_req, res) => {
try {
const r = await query(`
@@ -2692,6 +2712,16 @@ app.get('/magazine/:id', async (req, res) => {
LIMIT 3`,
[f.category_tag, id]
);
+ // Pull last 10 pipeline events for the underlying business (status changes, walks, replies, etc)
+ const events = await query(
+ `SELECT pel.event_type, pel.old_value, pel.new_value, pel.occurred_at
+ FROM pitch_event_log pel
+ JOIN pitches p ON p.id = pel.pitch_id
+ WHERE p.business_id = $1
+ ORDER BY pel.occurred_at DESC, pel.id DESC
+ LIMIT 10`,
+ [f.business_id]
+ );
// Pull building-mates: other businesses in the same canonical building
const bldg = (f.biz_address || '').replace(/\s*(SUITE|STE|UNIT|#).*$/i, '').trim();
const mates = bldg ? await query(
@@ -2767,6 +2797,17 @@ footer{margin-top:48px;padding:24px 0;text-align:center;font-size:10px;letter-sp
<dt>Generated</dt><dd class="mono">${new Date(f.generated_at).toLocaleString('en-US', { month:'short', day:'numeric', year:'numeric'})} via ${esc(f.model)}</dd>
<dt>Views</dt><dd class="mono">${f.views || 0}</dd>
</dl>
+ ${events.rows.length > 0 ? `<details style="margin-top:48px;padding-top:24px;border-top:1px solid var(--rule)">
+ <summary style="cursor:pointer;font-size:9px;letter-spacing:.32em;text-transform:uppercase;color:var(--ink-mute);font-family:'Inter',sans-serif">Editorial dossier · ${events.rowCount} pipeline events</summary>
+ <div style="margin-top:14px;font-family:'JetBrains Mono',monospace;font-size:11px;line-height:1.7;color:var(--ink-mute)">
+ ${events.rows.map((ev: any) => {
+ const arrow = ev.old_value ? `${esc(ev.old_value)} → ${esc(ev.new_value || '')}` : esc(ev.new_value || '');
+ const ts = new Date(ev.occurred_at).toLocaleString('en-US',{month:'short',day:'numeric',hour:'2-digit',minute:'2-digit'});
+ return `<div><span style="color:var(--metal)">${ts}</span> · <span style="color:var(--ink)">${esc(ev.event_type)}</span>${arrow ? ' · ' + arrow : ''}</div>`;
+ }).join('')}
+ </div>
+ <div style="margin-top:8px;font-size:10px;color:var(--ink-mute);font-style:italic">From the DW outreach pipeline that produces the magazine — every walk, every reply, every status change.</div>
+ </details>` : ''}
${mates.rows.length > 0 ? `<section style="margin-top:48px;padding-top:24px;border-top:1px solid var(--rule)">
<div style="font-size:9px;letter-spacing:.32em;text-transform:uppercase;color:var(--ink-mute);margin-bottom:14px">In the same building · ${esc(bldg)}</div>
<div style="display:flex;flex-direction:column;gap:6px">
← 97d5a13 iter 111+112: /api/magazine/:id/embed.html iframe-friendly m
·
back to Ventura Corridor
·
iter 115+116+117: og/twitter/JSON-LD meta + /api/magazine.js cfd5c5a →