Abstract amber glass software interface visual.
Back to blog
Coding6 min read

Build an MDX Blog With Next.js and Shiki

Learn how this site became a real MDX blog with static Next.js routes, SEO metadata, Shiki code blocks, topic filters, and a clean writing workflow.

By Suryansh Kushwaha /

Next.jsMDXShiki
On this page

The old site already had a Blog link. It was visible in the navigation, present in the footer, and previewed on the home page. What it did not have was a real writing system behind it.

This first post is the smallest useful version of that system: MDX files for authored posts, frontmatter for metadata, static article routes, topic filters, and Shiki-powered code blocks that inherit the same amber design language as the rest of the site.

The shape I wanted

I did not want the blog to feel like a bolted-on docs section. The rest of this site is direct, product-minded, and proof-heavy, so the writing system needed to support that same rhythm:

  • short essays that are easy to scan;
  • practical build notes with code when it helps;
  • enough metadata for SEO, previews, and future feeds;
  • a structure where adding a post only means adding one MDX file.

The important choice was separating content from presentation. Posts live as MDX. The index and article shell read metadata from frontmatter. The UI components then decide how that content should feel on the page.

Why MDX

Plain Markdown is excellent until an article needs one richer element. MDX keeps the writing close to Markdown while still allowing React components when a post needs a callout, comparison table, diagram, or demo.

For this site, the first version keeps the MDX surface intentionally narrow. It supports normal headings, lists, quotes, links, tables, callouts, inline code, images, and code blocks. More interactive pieces can arrive when the articles actually need them.

content/blog/new-post.mdx
---
title: A New Post
description: The short preview shown in the blog archive.
topic: coding
tags:
  - Next.js
---

That frontmatter is deliberately boring. It gives the blog index, topic filters, article metadata, and home-page preview one shared source of truth. Publication and update dates are detected from Git by default, with publishedAt and updatedAt still available when a post needs an explicit override.

Why Shiki

Code examples should be readable in both light and dark mode without creating a second visual language. Shiki handles the syntax parsing, while this site keeps the colors token-backed through CSS variables.

That means code blocks can highlight TypeScript, JSX, shell snippets, and future examples without hardcoding a separate palette.

app/blog/[slug]/page.tsx
export function generateStaticParams() {
  return getAllBlogPosts().map((post) => ({
    slug: post.slug,
  }));
}

The result is simple: the routes are static, invalid slugs return a 404, and the same frontmatter powers the surrounding article chrome.

What comes next

This is intentionally not the final form. It is the foundation.

The next useful additions are not more framework machinery. They are better articles, then features justified by those articles: copyable code blocks, tables of contents, RSS, search, and small interactive diagrams where they make an idea easier to understand.

For now, the blog has the thing it was missing most: a real path from an idea to a published page.