This site started as a single-page portfolio with no blog at all. Adding one meant picking a content model, and I went with the simplest thing that could work: MDX files committed straight into the repo, no headless CMS, no database.
Why not a CMS
For a solo blog with one author, a CMS mostly adds surface area: another account, another API to integrate, another thing that can go down independently of the site itself. Content-as-code gets me:
- Version control for free. Every post's edit history is just
git log. - No new infrastructure. The blog deploys with the rest of the site, on the same build.
- Portability. Markdown/MDX files aren't locked into a vendor's export format.
The tradeoff is obvious — no editorial UI, no scheduling dashboard, no non-technical authors. For this use case, that's a fine trade.
How it's wired up
Posts live in src/content/blog/*.mdx with YAML frontmatter (title, description, date, tags). A small helper in src/lib/blog.ts reads that directory with Node's fs module, parses frontmatter with gray-matter, and computes an estimated read time with reading-time.
The routes are plain Next.js App Router:
/bloglists every post, newest first./blog/[slug]renders one post, usinggenerateStaticParamsto pre-render every slug at build time andnext-mdx-remote/rscto compile the MDX body into React on the server.
Each post also emits its own BlogPosting JSON-LD, with author and publisher both pointing back at the same Person entity @id already declared site-wide — so a search engine reading this post and a search engine reading the homepage see the same person, not two disconnected records.
What's next
The infrastructure is the boring part. The actual content plan — topics, cadence, what's worth writing about — comes next.