diff --git a/src/app/head.tsx b/src/app/head.tsx
new file mode 100644
index 0000000..def451a
--- /dev/null
+++ b/src/app/head.tsx
@@ -0,0 +1,5 @@
+export default function Head() {
+ return (
+
+ );
+}
diff --git a/src/app/rss.xml/route.ts b/src/app/rss.xml/route.ts
new file mode 100644
index 0000000..806efa9
--- /dev/null
+++ b/src/app/rss.xml/route.ts
@@ -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, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+}
+
+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 [
+ "- ",
+ `${title}`,
+ `${link}`,
+ `${link}`,
+ `${description}`,
+ `${pubDate}`,
+ "
",
+ ].join("");
+ })
+ .join("");
+
+ const xml = [
+ '',
+ '',
+ "",
+ "Gaertan Art - Latest Artworks",
+ `${BASE_URL}`,
+ "Ten newest artworks from Gaertan Art.",
+ `${lastBuildDate}`,
+ itemXml,
+ "",
+ "",
+ ].join("");
+
+ return new Response(xml, {
+ headers: {
+ "Content-Type": "application/rss+xml; charset=utf-8",
+ },
+ });
+}
diff --git a/src/components/SocialLinks.tsx b/src/components/SocialLinks.tsx
index 1db36e5..b6a0be9 100644
--- a/src/components/SocialLinks.tsx
+++ b/src/components/SocialLinks.tsx
@@ -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({
})}
);
-}
\ No newline at end of file
+}