Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
eb8dcd54a8
|
|||
|
030065631c
|
|||
|
5a3e567ed5
|
@ -19,6 +19,11 @@ const geistMono = Geist_Mono({
|
|||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Gaertan Art",
|
title: "Gaertan Art",
|
||||||
description: "Portfolio, Artworks and Commission Requests",
|
description: "Portfolio, Artworks and Commission Requests",
|
||||||
|
alternates: {
|
||||||
|
types: {
|
||||||
|
"application/rss+xml": "/rss.xml",
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
|
|||||||
71
src/app/rss.xml/route.ts
Normal file
71
src/app/rss.xml/route.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
|
const BASE_URL = `${process.env.FEED_URL}`
|
||||||
|
|
||||||
|
function escapeXml(value: string): string {
|
||||||
|
return value
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.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 [
|
||||||
|
"<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",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -3,12 +3,20 @@ import {
|
|||||||
siLinktree,
|
siLinktree,
|
||||||
siMastodon,
|
siMastodon,
|
||||||
siPaypal,
|
siPaypal,
|
||||||
|
siRss,
|
||||||
siTelegram,
|
siTelegram,
|
||||||
siTwitch,
|
siTwitch,
|
||||||
type SimpleIcon,
|
type SimpleIcon,
|
||||||
} from "simple-icons";
|
} from "simple-icons";
|
||||||
|
|
||||||
type SocialKey = "paypal" | "telegram" | "mastodon" | "bluesky" | "linktree" | "twitch";
|
type SocialKey =
|
||||||
|
| "paypal"
|
||||||
|
| "telegram"
|
||||||
|
| "mastodon"
|
||||||
|
| "bluesky"
|
||||||
|
| "linktree"
|
||||||
|
| "twitch"
|
||||||
|
| "rss";
|
||||||
|
|
||||||
const SOCIALS: Record<
|
const SOCIALS: Record<
|
||||||
SocialKey,
|
SocialKey,
|
||||||
@ -43,7 +51,12 @@ const SOCIALS: Record<
|
|||||||
label: "Twitch",
|
label: "Twitch",
|
||||||
icon: siTwitch,
|
icon: siTwitch,
|
||||||
href: "https://www.twitch.tv/gaertan_art",
|
href: "https://www.twitch.tv/gaertan_art",
|
||||||
}
|
},
|
||||||
|
rss: {
|
||||||
|
label: "RSS",
|
||||||
|
icon: siRss,
|
||||||
|
href: `/rss.xml`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function BrandSvg({ icon }: { icon: SimpleIcon }) {
|
function BrandSvg({ icon }: { icon: SimpleIcon }) {
|
||||||
@ -60,7 +73,15 @@ function BrandSvg({ icon }: { icon: SimpleIcon }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function SocialLinks({
|
export function SocialLinks({
|
||||||
items = ["paypal", "telegram", "mastodon", "bluesky", "linktree", "twitch"],
|
items = [
|
||||||
|
"paypal",
|
||||||
|
"telegram",
|
||||||
|
"mastodon",
|
||||||
|
"bluesky",
|
||||||
|
"linktree",
|
||||||
|
"twitch",
|
||||||
|
"rss",
|
||||||
|
],
|
||||||
size = "md",
|
size = "md",
|
||||||
}: {
|
}: {
|
||||||
items?: SocialKey[];
|
items?: SocialKey[];
|
||||||
@ -99,4 +120,4 @@ export function SocialLinks({
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user