import { publicClient } from "@/lib/supabase"; export const runtime = "nodejs"; export const dynamic = "force-dynamic"; type PostRow = { slug: string; title: string; excerpt: string | null; published_at: string; }; function baseUrl(): string { return (process.env.PUBLIC_URL ?? "https://logicsrc.com").replace(/\/$/, ""); } function escapeXml(value: string): string { return value .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } // GET /blog/rss.xml — RSS 2.0 feed generated from published blog_posts. // Degrades to an empty (but valid) feed when Supabase is unavailable. export async function GET(): Promise { const base = baseUrl(); let posts: PostRow[] = []; try { const supabase = publicClient(); const { data } = await supabase .from("blog_posts") .select("slug, title, excerpt, published_at") .eq("status", "published") .order("published_at", { ascending: false }) .limit(50); posts = (data ?? []) as PostRow[]; } catch { posts = []; } const items = posts .map((post) => { const link = `${base}/blog/${post.slug}`; return ` ${escapeXml(post.title)} ${escapeXml(link)} ${escapeXml(link)} ${escapeXml(post.excerpt ?? "")} ${new Date(post.published_at).toUTCString()} `; }) .join("\n"); const xml = ` LogicSRC Blog ${base}/blog Project notes for LogicSRC OpenSpec standards, AgentSwarm, AgentByte, SDKs, MCP, and reference implementations. en-us ${items} `; return new Response(xml, { headers: { "content-type": "application/rss+xml; charset=utf-8", "cache-control": "public, max-age=300, s-maxage=300", }, }); }