Add rss feed with latest 10 artworks

This commit is contained in:
2026-01-31 11:46:21 +01:00
parent 84dc219a14
commit 5a3e567ed5
3 changed files with 101 additions and 4 deletions

5
src/app/head.tsx Normal file
View File

@ -0,0 +1,5 @@
export default function Head() {
return (
<link rel="alternate" type="application/rss+xml" href="/rss.xml" />
);
}

71
src/app/rss.xml/route.ts Normal file
View File

@ -0,0 +1,71 @@
import { prisma } from "@/lib/prisma";
const BASE_URL = `${process.env.BASE_URL}`
function escapeXml(value: string): string {
return value
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;");
}
export async function GET() {
const items = await prisma.artwork.findMany({
where: { published: true },
orderBy: { createdAt: "desc" },
take: 10,
select: {
id: true,
name: true,
description: true,
altText: true,
createdAt: true,
updatedAt: true,
},
});
const lastBuildDate =
items[0]?.updatedAt?.toUTCString() ?? new Date().toUTCString();
const itemXml = items
.map((item) => {
const title = escapeXml(item.name || "Artwork");
const description = escapeXml(
item.description || item.altText || item.name || "Artwork"
);
const link = `${BASE_URL}/artworks/single/${item.id}`;
const pubDate = item.createdAt.toUTCString();
return [
"<item>",
`<title>${title}</title>`,
`<link>${link}</link>`,
`<guid isPermaLink="true">${link}</guid>`,
`<description>${description}</description>`,
`<pubDate>${pubDate}</pubDate>`,
"</item>",
].join("");
})
.join("");
const xml = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<rss version="2.0">',
"<channel>",
"<title>Gaertan Art - Latest Artworks</title>",
`<link>${BASE_URL}</link>`,
"<description>Ten newest artworks from Gaertan Art.</description>",
`<lastBuildDate>${lastBuildDate}</lastBuildDate>`,
itemXml,
"</channel>",
"</rss>",
].join("");
return new Response(xml, {
headers: {
"Content-Type": "application/rss+xml; charset=utf-8",
},
});
}

View File

@ -3,12 +3,20 @@ import {
siLinktree,
siMastodon,
siPaypal,
siRss,
siTelegram,
siTwitch,
type SimpleIcon,
} from "simple-icons";
type SocialKey = "paypal" | "telegram" | "mastodon" | "bluesky" | "linktree" | "twitch";
type SocialKey =
| "paypal"
| "telegram"
| "mastodon"
| "bluesky"
| "linktree"
| "twitch"
| "rss";
const SOCIALS: Record<
SocialKey,
@ -43,7 +51,12 @@ const SOCIALS: Record<
label: "Twitch",
icon: siTwitch,
href: "https://www.twitch.tv/gaertan_art",
}
},
rss: {
label: "RSS",
icon: siRss,
href: "/rss.xml",
},
};
function BrandSvg({ icon }: { icon: SimpleIcon }) {
@ -60,7 +73,15 @@ function BrandSvg({ icon }: { icon: SimpleIcon }) {
}
export function SocialLinks({
items = ["paypal", "telegram", "mastodon", "bluesky", "linktree", "twitch"],
items = [
"paypal",
"telegram",
"mastodon",
"bluesky",
"linktree",
"twitch",
"rss",
],
size = "md",
}: {
items?: SocialKey[];
@ -99,4 +120,4 @@ export function SocialLinks({
})}
</div>
);
}
}