slice 1+2: header social URLs, drop TwitterX/Press Kit, wrap About/Team/PressKit, add /newsletter + /rss
- Header.tsx: bare linkedin/instagram/facebook URLs → /broadcastbeat handles; remove TwitterXIcon from social bar + import (Footer retains TwitterXIcon per "DO NOT OVERRIDE" marker) - AboutDropdown.tsx: drop "Press kit" item (the page itself stays at /about/press-kit, just delisted from menu) - SystemStatusBar.tsx: remove "Index online" pulse-dot and "N wire sources" span (keep articles count + events count + build version) - /about, /about/team, /about/press-kit: wrap in Header+Footer (previously rendered bare <main>) - /newsletter/page.tsx (new): redirect to /newsletter/archive — Header was 404'ing on /newsletter - /rss/route.ts (new): dynamic RSS feed reading from legacy-source news section; replaces 404 at /rss Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
60
src/app/rss/route.ts
Normal file
60
src/app/rss/route.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { getLegacyArticlesBySection } from "@/lib/articles/legacy-source";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
export const revalidate = 1800;
|
||||
|
||||
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || "https://broadcastbeat.com";
|
||||
|
||||
function escapeXml(s: string): string {
|
||||
return s
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
let items = "";
|
||||
try {
|
||||
const articles = await getLegacyArticlesBySection("news", 50);
|
||||
items = articles
|
||||
.map((a) => {
|
||||
const url = `${SITE_URL}/news/${a.slug}`;
|
||||
const pubDate = a.date ? new Date(a.date).toUTCString() : new Date().toUTCString();
|
||||
const title = escapeXml(a.title || "Untitled");
|
||||
const description = escapeXml(a.excerpt || "");
|
||||
return ` <item>
|
||||
<title>${title}</title>
|
||||
<link>${url}</link>
|
||||
<guid isPermaLink="true">${url}</guid>
|
||||
<pubDate>${pubDate}</pubDate>
|
||||
<description>${description}</description>
|
||||
</item>`;
|
||||
})
|
||||
.join("\n");
|
||||
} catch {
|
||||
// serve an empty but valid feed on failure
|
||||
items = "";
|
||||
}
|
||||
|
||||
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>BroadcastBeat</title>
|
||||
<link>${SITE_URL}</link>
|
||||
<atom:link href="${SITE_URL}/rss" rel="self" type="application/rss+xml" />
|
||||
<description>News & Intelligence for Broadcast, Post-Production & Streaming Technology</description>
|
||||
<language>en-us</language>
|
||||
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
|
||||
${items}
|
||||
</channel>
|
||||
</rss>`;
|
||||
|
||||
return new Response(body, {
|
||||
headers: {
|
||||
"Content-Type": "application/rss+xml; charset=utf-8",
|
||||
"Cache-Control": "public, max-age=1800, s-maxage=1800, stale-while-revalidate=3600",
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user