All writing

How this blog is built

A clean, content-first Next.js engine: MDX files, a tiny taxonomy, static search, GitHub-backed comments, and likes that survive a redeploy. A tour of the moving parts.

2 min read

I wanted a blog I would still want to write in three years from now: fast, mine, and boring in all the right ways. Here is how this one is put together.

Posts are just files

Every post is an MDX file in content/posts. Frontmatter carries the metadata; the body is plain Markdown. No CMS, no database, fully version-controlled:

---
title: "How this blog is built"
date: "2026-06-12"
category: "engineering"
subcategory: "frontend"
tags: ["nextjs", "mdx", "tailwind"]
---

Posts are just files...

A small library reads the folder, parses frontmatter with gray-matter, computes reading time, and hands typed objects to the pages. Adding a post means adding a file — that is the whole publishing pipeline.

A taxonomy with two levels, plus tags

The structure is deliberately small: a handful of categories, each with one level of sub-categories, defined in a single file. Tags are free-form and cut across everything.

export const categories = [
  {
    slug: "engineering",
    title: "Engineering",
    subcategories: [
      { slug: "frontend", title: "Frontend" },
      { slug: "systems", title: "Systems & Backend" },
    ],
  },
  // ...
];

The rule I am holding myself to: do not add a bucket until a post actually needs it. Empty categories make a blog look abandoned.

Search, comments, likes

The three "interactive" features are each as light as they can be:

  • Search is a static index over post metadata, fuzzy-matched in the browser with Fuse.js. No server, no Algolia bill.
  • Comments are GitHub Discussions via Giscus. Signing in with GitHub kills drive-by spam and gives me moderation for free.
  • Likes are a tiny API route backed by Redis in production, with a local file fallback so the button works in dev with zero setup.

Why this stack

It compiles to mostly static pages, ships almost no JavaScript for an essay, and every piece is replaceable. The best part: the whole thing is one config file away from becoming a different person's blog — which is exactly how the second one in this little family of sites will get built.

Slow web, built to last.

Written by Manohar Negi in Bengaluru, India.

Get new writing in your inbox

No schedule, no spam — just new essays when they’re ready. The slow web, delivered slowly.

Comments

Sign in with GitHub to join the conversation.

Comments aren’t wired up yet. Enable GitHub Discussions on your repo, visit giscus.app to get your IDs, then fill the giscus block in src/site.config.ts. Sign-in via GitHub keeps it spam-free and moderated.