forked from
danabra.mov/overreacted
my blog https://overreacted.io
1import { readdir, readFile } from "fs/promises";
2import matter from "gray-matter";
3import { Feed } from "feed";
4
5export interface Post {
6 slug: string;
7 title: string;
8 date: string;
9 spoiler: string;
10 youtube?: string;
11 bluesky?: string;
12}
13
14export const metadata = {
15 title: "overreacted — A blog by Dan Abramov",
16 description: "A blog by Dan Abramov",
17 openGraph: {
18 title: "overreacted",
19 },
20 alternates: {
21 types: {
22 "application/atom+xml": "https://overreacted.io/atom.xml",
23 "application/rss+xml": "https://overreacted.io/rss.xml",
24 },
25 },
26};
27
28export async function getPosts(): Promise<Post[]> {
29 const entries = await readdir("./public/", { withFileTypes: true });
30 const dirs = entries
31 .filter((entry) => entry.isDirectory())
32 .map((entry) => entry.name);
33 const fileContents = await Promise.all(
34 dirs.map((dir) => readFile("./public/" + dir + "/index.md", "utf8")),
35 );
36 const posts = dirs.map((slug, i) => {
37 const fileContent = fileContents[i];
38 const { data } = matter(fileContent);
39 return { slug, ...data };
40 });
41 posts.sort((a: any, b: any) => {
42 return Date.parse(a.date) < Date.parse(b.date) ? 1 : -1;
43 });
44 return posts as Post[];
45}
46
47export async function generateFeed() {
48 const posts = await getPosts();
49 const site_url = "https://overreacted.io/";
50
51 const feedOptions = {
52 author: {
53 name: "Dan Abramov",
54 email: "dan.abramov@gmail.com",
55 link: site_url,
56 },
57 description: metadata.description,
58 favicon: `${site_url}/icon.png`,
59 feedLinks: { atom: `${site_url}atom.xml`, rss: `${site_url}rss.xml` },
60 generator: "Feed for Node.js",
61 id: site_url,
62 image: "https://github.com/gaearon.png",
63 link: site_url,
64 title: metadata.title,
65 };
66
67 const feed = new Feed(feedOptions as any);
68
69 for (const post of posts) {
70 feed.addItem({
71 date: new Date(post.date),
72 description: post.spoiler,
73 id: `${site_url}${post.slug}/`,
74 link: `${site_url}${post.slug}/`,
75 title: post.title,
76 });
77 }
78
79 return feed;
80}