
I recently finished implementing the blog section of this personal website. Rather than reaching for a complex CMS, I decided to build it directly into my existing Next.js application using standard tools.
Low-Maintenance Publishing
I wanted a place to share technical thoughts without adding maintenance overhead. The requirements were simple:
- Write in Markdown: I want to write posts in VS Code.
- Zero Runtime Cost: The blog should be statically generated.
- Fast: It should feel instant.
Static by Default
1. Filesystem as the Database
I created a simple utility, blogApi.ts, that reads directly from the file system. It uses gray-matter to parse the frontmatter and a remark/rehype pipeline—specifically rehype-pretty-code—to process the content.
2. Static Routing
Next.js makes it straightforward to turn a folder of markdown files into routes. I used generateStaticParams to tell Next.js which paths to build at compile time:
export async function generateStaticParams() {
const posts = getAllPosts(["slug"]);
return posts.map((post) => ({
slug: post.slug,
}));
}
This ensures that alexleung.ca/blog/boring-blog-architecture is just a simple HTML file on the server, not a dynamic Node.js request.
3. Details That Mattered
To make it feel professional, I spent time on the details:
- Typography: I used
@tailwindcss/typographybut customized it to remove the default backticks from inline code for a cleaner look. - Metadata: Each post automatically generates its own SEO tags and JSON-LD structured data.
- Syntax Highlighting: I chose
rehype-pretty-code(powered by Shiki). It uses the same TextMate grammars as VS Code, meaning the highlighting is extremely accurate. Because it generates inline styles, there's no brittle CSS to import fromnode_modules. - Sitemap: A dynamic script crawls my posts directory to keep
sitemap.xmlup to date automatically.
This "boring" architecture lets me focus on writing, with a rendering path that is predictable and fast.
Get new posts by email
Subscribe for occasional updates when I publish something new.
Related posts
Making Responsive Images Just Work
March 4, 2026
Instead of manually managing -sm/-md/-lg assets, I moved to a manifest-driven workflow that reduced duplication and made performance outcomes more consistent.
Dropout as Implicit Bagging
March 7, 2026
Chapter 7 clarified that dropout works so well because it approximates bagging over many thinned networks with shared parameters.
iPad Air M3 11-Inch: First Impressions
March 5, 2026
For study-heavy workflows, a lightweight iPad Air setup with a keyboard, stand, and Pencil Pro can be a practical laptop replacement.