1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-07-19 05:35:30 -04:00

Migrate to app router (#2254)

This commit is contained in:
2025-02-07 11:33:38 -05:00
committed by GitHub
parent e97613dda5
commit 8aabb4a66f
179 changed files with 4095 additions and 4951 deletions

View File

@@ -2,84 +2,58 @@ import { Feed } from "feed";
import { getAllPosts } from "./posts";
import config from "../config";
import { meJpg } from "../config/favicons";
import type { GetServerSideProps } from "next";
import { metadata } from "../../app/layout";
export type GetServerSideFeedProps = GetServerSideProps<Record<string, never>>;
export type BuildFeedOptions = {
format: "rss" | "atom" | "json";
};
// handles literally *everything* about building the server-side rss/atom feeds and writing the response.
// all the page needs to do is `return buildFeed(context, "rss")` from getServerSideProps.
export const buildFeed = async (
context: Parameters<GetServerSideFeedProps>[0],
options: BuildFeedOptions
): Promise<ReturnType<GetServerSideFeedProps>> => {
const { res } = context;
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || `https://${config.siteDomain}`;
export const buildFeed = async (options: { type: "rss" | "atom" | "json" }): Promise<string> => {
const baseUrl = metadata.metadataBase?.href || `https://${config.siteDomain}/`;
// https://github.com/jpmonette/feed#example
const feed = new Feed({
id: `${baseUrl}/`,
link: `${baseUrl}/`,
id: baseUrl,
link: baseUrl,
title: config.siteName,
description: config.longDescription,
copyright: config.licenseUrl,
updated: new Date(process.env.RELEASE_DATE || Date.now()),
image: `${baseUrl}${meJpg.src}`,
image: new URL(meJpg.src, baseUrl).href,
feedLinks: {
rss: `${baseUrl}/feed.xml`,
atom: `${baseUrl}/feed.atom`,
rss: new URL("feed.xml", baseUrl).href,
atom: new URL("feed.atom", baseUrl).href,
},
author: {
name: config.authorName,
link: `${baseUrl}/`,
link: baseUrl,
email: config.authorEmail,
},
});
// add posts separately using their frontmatter
const posts = await getAllPosts();
posts.forEach((post) => {
(await getAllPosts()).forEach((post) => {
feed.addItem({
guid: post.permalink,
link: post.permalink,
title: post.title,
description: post.description,
image: post.image && `${baseUrl}${post.image}`,
image: post.image || undefined,
author: [
{
name: config.authorName,
link: `${baseUrl}/`,
link: baseUrl,
},
],
date: new Date(post.date),
});
});
// cache on edge for 24 hours by default
res.setHeader("cache-control", `public, max-age=0, s-maxage=86400, stale-while-revalidate`);
// generates RSS by default
if (options.format === "rss") {
res.setHeader("content-type", "application/rss+xml; charset=utf-8");
res.write(feed.rss2());
} else if (options.format === "atom") {
res.setHeader("content-type", "application/atom+xml; charset=utf-8");
res.write(feed.atom1());
} else if (options.format === "json") {
if (options.type === "rss") {
return feed.rss2();
} else if (options.type === "atom") {
return feed.atom1();
} else if (options.type === "json") {
// rare but including as an option because why not...
// https://www.jsonfeed.org/
res.setHeader("content-type", "application/feed+json; charset=utf-8");
res.write(feed.json1());
return feed.json1();
} else {
throw new TypeError(`Invalid feed type "${options.format}", must be "rss", "atom", or "json".`);
throw new TypeError(`Invalid feed type "${options.type}", must be "rss", "atom", or "json".`);
}
res.end();
return {
props: {},
};
};