Refactor to static markdown (remove Supabase backend) + self-host build

Posts now read from data/posts/*.md via gray-matter + remark; authors derived
from posts. Removes admin dashboard, comments, subscriptions, and all Supabase
usage. Adds Dockerfile (Next.js standalone) + Gitea Actions CI. output: standalone.
This commit is contained in:
2026-07-22 13:11:56 -05:00
parent 76f1241761
commit 10cd973e35
41 changed files with 214 additions and 2704 deletions
+57
View File
@@ -0,0 +1,57 @@
import { getSortedPostsData, getPostsByAuthor } from "@/lib/posts";
import { PostMetadata } from "@/types";
export interface AuthorSummary {
name: string;
slug: string;
postCount: number;
// No bio data is available in the static build; these remain optional.
bio?: string;
x_link?: string;
fb_link?: string;
insta_link?: string;
pfp_link?: string;
}
export interface AuthorWithPosts extends AuthorSummary {
posts: PostMetadata[];
}
/**
* Derive the list of authors from the posts' frontmatter.
* The author `slug` is the author name itself, which is what
* `getPostsByAuthor` filters on and what the `[author]` route uses.
*/
export async function getAllAuthors(): Promise<AuthorSummary[]> {
const posts = await getSortedPostsData();
const counts = new Map<string, number>();
for (const post of posts) {
if (!post.author) continue;
counts.set(post.author, (counts.get(post.author) || 0) + 1);
}
return Array.from(counts.entries())
.map(([name, postCount]) => ({
name,
slug: name,
postCount,
}))
.sort((a, b) => a.name.localeCompare(b.name));
}
export async function getAuthor(
name: string,
): Promise<AuthorWithPosts | null> {
const posts = await getPostsByAuthor(name);
if (posts.length === 0) {
return null;
}
return {
name,
slug: name,
postCount: posts.length,
posts,
};
}