← back to Ventura Corridor
fix: move RSS route ahead of /issue/:cat handler — Express was matching 'feed.xml' as a category and serving the HTML issue page; RSS route now defined first; /issue/:cat/feed.xml correctly returns RSS XML for vertical-specific feeds
a45aad19e0ced1287e71ccccbb49b3e47be26697 · 2026-05-06 17:38:38 -0700 · SteveStudio2
Files touched
Diff
commit a45aad19e0ced1287e71ccccbb49b3e47be26697
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Wed May 6 17:38:38 2026 -0700
fix: move RSS route ahead of /issue/:cat handler — Express was matching 'feed.xml' as a category and serving the HTML issue page; RSS route now defined first; /issue/:cat/feed.xml correctly returns RSS XML for vertical-specific feeds
---
src/server/index.ts | 90 ++++++++++++++++++++++++++++-------------------------
1 file changed, 48 insertions(+), 42 deletions(-)
diff --git a/src/server/index.ts b/src/server/index.ts
index 5670946..36e68e3 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1971,6 +1971,51 @@ Write the feature.`;
}
});
+// /issue/feed.xml or /issue/:cat/feed.xml — RSS feed (must be defined BEFORE /issue/:cat
+// or Express matches "feed.xml" as a category)
+app.get(['/issue/feed.xml', '/issue/:cat/feed.xml'], async (req, res) => {
+ try {
+ const cat = (req.params as any).cat || null;
+ const baseUrl = process.env.PUBLIC_BASE_URL || 'http://127.0.0.1:9780';
+ const where: string[] = [`status = 'published'`];
+ const params: any[] = [];
+ if (cat) { params.push(cat); where.push(`category_tag = $${params.length}`); }
+ const r = await query(
+ `SELECT mf.id, mf.headline, mf.subhead, mf.editorial, mf.published_at, mf.category_tag,
+ b.name AS biz_name
+ FROM magazine_features mf JOIN businesses b ON b.id = mf.business_id
+ WHERE ${where.join(' AND ')}
+ ORDER BY published_at DESC LIMIT 50`,
+ params
+ );
+ const esc = (s: any) => String(s ?? '').replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]!));
+ const items = r.rows.map((f: any) => `
+ <item>
+ <title>${esc(f.headline || f.biz_name)}</title>
+ <link>${baseUrl}/magazine/${f.id}</link>
+ <guid isPermaLink="true">${baseUrl}/magazine/${f.id}</guid>
+ <pubDate>${new Date(f.published_at || Date.now()).toUTCString()}</pubDate>
+ <category>${esc(f.category_tag || 'feature')}</category>
+ <description>${esc(f.subhead || '')} — ${esc(f.biz_name)}</description>
+ <content:encoded><![CDATA[${esc(f.editorial || '')}]]></content:encoded>
+ </item>`).join('');
+ const title = cat ? `The Corridor — ${cat}` : 'The Corridor';
+ res.setHeader('Content-Type', 'application/rss+xml; charset=utf-8');
+ res.send(`<?xml version="1.0" encoding="UTF-8"?>
+<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
+ <channel>
+ <title>${esc(title)}</title>
+ <link>${baseUrl}${cat ? '/issue/' + esc(cat) : '/issue'}</link>
+ <description>A magazine of who's here on Ventura Boulevard.${cat ? ' Vertical: ' + esc(cat) + '.' : ''}</description>
+ <language>en-us</language>
+ <lastBuildDate>${new Date().toUTCString()}</lastBuildDate>${items}
+ </channel>
+</rss>`);
+ } catch (e: any) {
+ res.status(500).send('error: ' + e.message);
+ }
+});
+
// /issue — the curated public-facing issue (status='published' only)
// Mirrors /magazine.html aesthetic but stripped of admin controls + prints clean.
app.get(['/issue', '/issue/:cat'], async (req, res) => {
@@ -2111,48 +2156,9 @@ ${urls.join('\n')}
}
});
-// /issue/feed.xml or /issue/:cat/feed.xml — RSS for the (vertical-) issue
-app.get(['/issue/feed.xml', '/issue/:cat/feed.xml'], async (req, res) => {
- try {
- const cat = (req.params as any).cat || null;
- const baseUrl = process.env.PUBLIC_BASE_URL || 'http://127.0.0.1:9780';
- const where: string[] = [`status = 'published'`];
- const params: any[] = [];
- if (cat) { params.push(cat); where.push(`category_tag = $${params.length}`); }
- const r = await query(
- `SELECT mf.id, mf.headline, mf.subhead, mf.editorial, mf.published_at, mf.category_tag,
- b.name AS biz_name
- FROM magazine_features mf JOIN businesses b ON b.id = mf.business_id
- WHERE ${where.join(' AND ')}
- ORDER BY published_at DESC LIMIT 50`,
- params
- );
- const esc = (s: any) => String(s ?? '').replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]!));
- const items = r.rows.map((f: any) => `
- <item>
- <title>${esc(f.headline || f.biz_name)}</title>
- <link>${baseUrl}/magazine/${f.id}</link>
- <guid isPermaLink="true">${baseUrl}/magazine/${f.id}</guid>
- <pubDate>${new Date(f.published_at || Date.now()).toUTCString()}</pubDate>
- <category>${esc(f.category_tag || 'feature')}</category>
- <description>${esc(f.subhead || '')} — ${esc(f.biz_name)}</description>
- <content:encoded><![CDATA[${esc(f.editorial || '')}]]></content:encoded>
- </item>`).join('');
- const title = cat ? `The Corridor — ${cat}` : 'The Corridor';
- res.setHeader('Content-Type', 'application/rss+xml; charset=utf-8');
- res.send(`<?xml version="1.0" encoding="UTF-8"?>
-<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
- <channel>
- <title>${esc(title)}</title>
- <link>${baseUrl}${cat ? '/issue/' + esc(cat) : '/issue'}</link>
- <description>A magazine of who's here on Ventura Boulevard.${cat ? ' Vertical: ' + esc(cat) + '.' : ''}</description>
- <language>en-us</language>
- <lastBuildDate>${new Date().toUTCString()}</lastBuildDate>${items}
- </channel>
-</rss>`);
- } catch (e: any) {
- res.status(500).send('error: ' + e.message);
- }
+// (RSS route moved earlier — see /issue/feed.xml above)
+app.get('/__rss-removed', (_req, res) => {
+ res.status(410).send('moved');
});
app.get('/robots.txt', (_req, res) => {
← fa94a30 iter 104+105+106+107+108: regen-thin job + sitemap + robots
·
back to Ventura Corridor
·
iter 109+110: building-mates on /magazine/:id reader + score 715edc1 →