Rajasekar Writes
← All posts

How this blog is built

1 min read

  • nextjs
  • markdown
  • meta

This site is a small Next.js app. Posts are plain Markdown files, and every page is prerendered at build time.

The moving parts

Piece What it does
content/posts/*.md One file per post, with YAML frontmatter
gray-matter Splits frontmatter from the Markdown body
remark + rehype Parse Markdown (with GitHub Flavored Markdown) and turn it into HTML
shiki Syntax highlighting with light and dark themes
@tailwindcss/typography Readable defaults for the rendered article

Writing a post

Create a new file in content/posts/ named after the URL slug you want, for example my-first-post.md:

---
title: "My first post"
date: 2026-10-01
description: "One sentence that shows up in lists and search results."
tags: [react]
publish: true
---

Write your post here.

A post only goes public once its frontmatter has publish: true. Leave it out, or set it to false, to keep a post private while you work on it. Unpublished posts still show up locally under next dev, marked with an "Unpublished" badge.

The blog index shows six posts per page. Older posts move to /blog/page/2, /blog/page/3 and so on, and every page is prerendered.

Rendering pipeline

The whole pipeline is one unified processor:

const processor = unified()
  .use(remarkParse)
  .use(remarkGfm)
  .use(remarkRehype)
  .use(rehypeSlug)
  .use(rehypeShiki, {
    themes: { light: "github-light", dark: "github-dark" },
    defaultColor: false,
  })
  .use(rehypeStringify);

Each post page calls generateStaticParams, so every post becomes a static HTML file. There is no database and no runtime Markdown parsing.

Keep content as data and let the framework do the rest.

That is the whole idea.