How we built the byte5 blog
We wanted a blog that feels like the rest of byte5.ai: fast, static, no database, no vendor lock-in. No headless CMS, no external API — content lives as files in the repository and goes through the same review process as code.
This post walks through the architecture behind it and why it scales well for a multilingual team.
Content as files#
Every post is one MDX file per language plus a typed entry in the registry. The registry holds all language-independent fields — date, tags, author, cover:
export const posts: BlogPostMeta[] = [
{
slug: "wie-wir-den-byte5-blog-gebaut-haben",
publishedAt: "2026-05-20",
tags: ["MDX", "Next.js", "Engineering", "byte5"],
authorId: "christian-wendler",
sourceLanguage: "de",
},
];The nice part: filtering and sorting on the overview run purely on this typed data. The actual prose stays where it belongs — in the MDX file.
Content belongs in the repository, not in a database. That way every blog post gets the same care as any code change: branch, review, diff.
From markdown to a server component#
The MDX files are compiled at build/render time and rendered as a React Server Component. Syntax highlighting is handled by Shiki — entirely on the server, without shipping a single kilobyte of JavaScript to the browser:
Why no client library?#
Highlighting, heading anchors and GitHub-flavored markdown all happen at render time. The browser receives finished HTML. That keeps pages light and Core Web Vitals green.
Prepare, don't rush#
One detail mattered to us: posts with a publish date in the future do not appear in the overview — yet the detail page is already reachable by link. So posts can be prepared calmly and go live automatically once their date arrives.
export const revalidate = 600;
export default async function BlogIndex() {
const now = Date.now(); // always evaluate at render time
const published = getPublishedPosts(now);
// ...
}Multilingual support rounds it out: a post is written in German or English and translated into the remaining languages. If a translation is missing, the page falls back cleanly to the source language and shows a subtle language badge.
The result is a blog that is technically boring — in the best sense. That is exactly what we wanted.