diff --git a/app/rss.xml/route.ts b/app/rss.xml/route.ts new file mode 100644 index 0000000..3de436d --- /dev/null +++ b/app/rss.xml/route.ts @@ -0,0 +1,86 @@ +import { getAllBlogArticles } from "@/data/blog"; + +const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || "https://poyrazavsever.com"; +const FEED_PATH = "/rss.xml"; +const FEED_TITLE = "Poyraz Avsever Blog"; +const FEED_DESCRIPTION = + "Poyraz Avsever'in blog yazilari, yazilim notlari ve teknik icerikleri."; + +function toAbsoluteUrl(pathOrUrl: string) { + try { + return new URL(pathOrUrl).toString(); + } catch { + return new URL(pathOrUrl, SITE_URL).toString(); + } +} + +function escapeXml(value: string) { + return value + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + +function toRssDate(value: string | undefined) { + if (!value) return new Date().toUTCString(); + const timestamp = Date.parse(value); + if (Number.isNaN(timestamp)) return new Date().toUTCString(); + return new Date(timestamp).toUTCString(); +} + +export async function GET() { + const articles = await getAllBlogArticles(); + const feedUrl = toAbsoluteUrl(FEED_PATH); + const siteUrl = toAbsoluteUrl("/"); + + const lastBuildDate = toRssDate(articles[0]?.date); + + const items = articles + .map((article) => { + const link = toAbsoluteUrl(article.href); + const pubDate = toRssDate(article.date); + const title = escapeXml(article.title); + const description = escapeXml(article.excerpt || article.title); + const category = escapeXml(article.category || "General"); + const author = escapeXml(article.author || "Poyraz Avsever"); + + return [ + " ", + ` ${title}`, + ` ${link}`, + ` ${link}`, + ` ${description}`, + ` ${category}`, + ` hello@poyrazavsever.com (${author})`, + ` ${pubDate}`, + " ", + ].join("\n"); + }) + .join("\n"); + + const xml = [ + '', + '', + " ", + ` ${escapeXml(FEED_TITLE)}`, + ` ${siteUrl}`, + ` ${escapeXml(FEED_DESCRIPTION)}`, + " tr-TR", + ` `, + ` ${lastBuildDate}`, + " Next.js RSS Route", + items, + " ", + "", + "", + ].join("\n"); + + return new Response(xml, { + headers: { + "Content-Type": "application/rss+xml; charset=utf-8", + "Cache-Control": "public, s-maxage=3600, stale-while-revalidate=86400", + }, + }); +}