All postslib/posts.ts
Hello, World: This Site Has a Blog Now
Why I bolted a minimal MDX blog onto my portfolio instead of reaching for a blog platform.
I write software for a living, so naturally the hardest part of starting a blog was resisting the urge to build a CMS first. This blog is deliberately boring: MDX files in a folder, statically rendered at build time. No database, no admin panel, no excuses.
How it works
Every post is a single .mdx file in content/posts/. Front matter carries
the metadata, and the body is Markdown with JSX available when I need it.
export function getAllPosts(options?: { includeDrafts?: boolean }): Post[] {
return fs
.readdirSync(POSTS_DIR)
.filter((file) => file.endsWith(".mdx"))
.map((file) => readPost(POSTS_DIR, file))
.filter((post) => options?.includeDrafts || !post.draft)
.sort((a, b) => b.date.localeCompare(a.date))
}Publishing a post is a git commit. Drafts are a draft: true flag away from
the public eye. That's the whole platform.
What I'll write about
Mostly the things I run into building and running real products:
- Next.js and TypeScript patterns that earned their keep
- Running Mosaic Ridge — the business side of shipping
- The occasional lesson learned the hard way
Ship the thing. Write about it after.
More soon.