mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
Phase 5: every page of the site, the resume PDF and RSS
Landing, About, Now, Resume (with a generated PDF), Work and case studies, Inquiries and the sent page, Library and the Shelf, Workshop and craft pages, Tabletop, Blog with topics and posts, RSS, the Store, product lines, the order form and the 404, all rendered from the content service's notes. Schema: experience previousRoles, skills stack core items, page stats, make tags and deck favorite. Icon names from notes map to brand icons in one place, and HTML comments are dropped when Markdown renders. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* The RSS 2.0 feed: blog posts and case studies, newest first, with absolute
|
||||
* links from the configured site address or the request's origin.
|
||||
*/
|
||||
import type { APIRoute } from "astro";
|
||||
import { xml } from "../lib/blog.ts";
|
||||
import { site } from "../lib/page.ts";
|
||||
|
||||
export const GET: APIRoute = async ({ site: configured, url }) => {
|
||||
const s = await site();
|
||||
const origin = (configured ?? new URL(url.origin)).href.replace(/\/$/, "");
|
||||
const abs = (path: string) => new URL(path, `${origin}/`).href;
|
||||
const settings = s.settings();
|
||||
const name = settings?.name ?? "Greg Kilmer";
|
||||
const posts = s.posts({ includeCaseStudies: true }).slice(0, 50);
|
||||
const rfc822 = (iso: string) => new Date(`${iso}T12:00:00Z`).toUTCString();
|
||||
|
||||
const items = posts
|
||||
.map((p) => {
|
||||
const href = s.href(p);
|
||||
if (!href) return "";
|
||||
const link = abs(href);
|
||||
const category = p.data.postType === "case study" ? "Case study" : p.data.topic;
|
||||
return [
|
||||
" <item>",
|
||||
` <title>${xml(p.title)}</title>`,
|
||||
` <link>${xml(link)}</link>`,
|
||||
` <guid isPermaLink="true">${xml(link)}</guid>`,
|
||||
` <pubDate>${rfc822(p.data.date)}</pubDate>`,
|
||||
` <category>${xml(category)}</category>`,
|
||||
p.data.summary ? ` <description>${xml(p.data.summary)}</description>` : "",
|
||||
" </item>",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
|
||||
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>${xml(name)}</title>
|
||||
<link>${xml(abs("/blog"))}</link>
|
||||
<atom:link href="${xml(abs("/rss.xml"))}" rel="self" type="application/rss+xml" />
|
||||
<description>${xml(settings?.tagline ?? "What I am making, learning, playing and building.")}</description>
|
||||
<language>en-us</language>
|
||||
${posts[0] ? ` <lastBuildDate>${rfc822(posts[0].data.date)}</lastBuildDate>\n` : ""}${items}
|
||||
</channel>
|
||||
</rss>
|
||||
`;
|
||||
return new Response(body, { headers: { "content-type": "application/rss+xml; charset=utf-8", "cache-control": "public, max-age=600" } });
|
||||
};
|
||||
Reference in New Issue
Block a user