[object Object]

← back to Ventura Corridor

iter 134: /api/magazine/today unified payload — feature + caption + tags + share/audio for IG-autopost

f40d96ecbadb354486022c5c02b5d5bafe4099f3 · 2026-05-06 18:54:09 -0700 · SteveStudio2

Files touched

Diff

commit f40d96ecbadb354486022c5c02b5d5bafe4099f3
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Wed May 6 18:54:09 2026 -0700

    iter 134: /api/magazine/today unified payload — feature + caption + tags + share/audio for IG-autopost
---
 src/server/index.ts | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/src/server/index.ts b/src/server/index.ts
index a0130eb..af7232b 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1823,6 +1823,46 @@ app.get('/api/magazine/feature-of-the-day', async (_req, res) => {
   }
 });
 
+// Unified daily payload — what an IG-autopost / morning-email / standup-audio job needs in one call.
+app.get('/api/magazine/today', async (_req, res) => {
+  try {
+    const r = await query(`
+      SELECT mf.id, mf.headline, mf.subhead, mf.editorial, mf.pull_quote, mf.category_tag,
+             mf.published_at, mf.views, mf.taps,
+             b.name AS biz_name, b.address AS biz_address, b.city, b.zip
+      FROM magazine_features mf
+      JOIN businesses b ON b.id = mf.business_id
+      WHERE mf.editorial IS NOT NULL AND length(mf.editorial) > 200
+        AND mf.status IN ('published','reviewed')
+      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 });
+    const f = r.rows[0];
+    const tags = ['#TheCorridor', '#VenturaBoulevard', '#LosAngeles'];
+    if (f.category_tag) tags.push('#' + String(f.category_tag).replace(/[^a-z0-9]/gi, ''));
+    if (f.city) tags.push('#' + String(f.city).replace(/\s+/g, ''));
+    const caption =
+      `${f.headline}\n\n` +
+      (f.subhead ? `${f.subhead}\n\n` : '') +
+      `${(f.editorial as string).slice(0, 380).replace(/\s+\S*$/, '')}…\n\n` +
+      `Read the full feature → /magazine/${f.id}\n\n` +
+      tags.join(' ');
+    res.json({
+      date: new Date().toISOString().slice(0, 10),
+      feature: f,
+      permalink: `/magazine/${f.id}`,
+      share_card: `/share/${f.id}`,
+      audio: `/api/magazine/${f.id}/audio.m4a`,
+      tags,
+      caption,
+      caption_chars: caption.length,
+    });
+  } catch (e: any) {
+    res.status(500).json({ error: e.message });
+  }
+});
+
 // Random published feature — for fleet-tv-style rotators or sidebar widgets
 app.get('/api/magazine/random', async (req, res) => {
   try {

← 97c9f08 iter 133: 404 page now suggests a random published feature  ·  back to Ventura Corridor  ·  iter 135: IG-autopost dry-run job — writes daily JSON+HTML d 85d3731 →