Why NextWhy Next
Zur Übersicht
💻 Entwicklung3 Min. Lesezeit

Einen MDX-Blog mit Next.js selbst bauen - So ist dieser Blog entstanden

Wie dieser Blog ohne CMS, nur mit Markdown-Dateien und dem Next.js 16 App Router entstanden ist. Ordnerstruktur, MDX-Setup und SEO, erklärt am echten Code.

Das Wichtigste

Beiträge liegen als .mdx-Dateien unter src/content/posts und werden mit @next/mdx gerendert, ganz ohne CMS. Der Dateiname ist die URL, und statt Frontmatter liefert ein meta-Export Liste und Metadaten.

Auf dieser Seite

Dieser Blog, den Sie gerade lesen, hat weder eine Datenbank noch ein Admin-Panel. Jeder Beitrag ist eine einzige Markdown-Datei. Hier zeige ich genau, wie er entstanden ist.

Warum dateibasiert

Blog-Tools gibt es viele, aber für Solo-Entwickler sind die meisten überdimensioniert.

  • CMS: bringt Admin-Oberfläche, Integrationen und Kosten mit sich
  • Notion-Anbindung: bequem, aber bei Rendering, Geschwindigkeit und Anpassungen stößt man an Grenzen
  • Markdown-Dateien: Beiträge werden mit dem Code versioniert, kosten nichts, und git push ist die Veröffentlichung

Ich habe mich für die dritte Option entschieden. Sie hat die geringste Reibung.

Ordnerstruktur

Aufs Wesentliche reduziert sieht sie so aus:

src/
├── app/
│   ├── page.tsx              # 홈 - 글 목록
│   ├── posts/[slug]/page.tsx # 글 상세
│   └── sitemap.ts            # /sitemap.xml
├── content/posts/*.mdx       # ← 글은 여기에만 추가
└── lib/posts.ts              # 목록·메타 로딩

Der Dateiname wird zur URL. hello.mdx ist unter /posts/hello erreichbar.

MDX-Setup

Um MDX im App Router zu nutzen, kommt @next/mdx dazu. In Next 16 ist Turbopack der Standard, deshalb müssen remark/rehype-Plugins als String-Namen übergeben werden (Funktionsreferenzen funktionieren nicht).

const withMDX = createMDX({
  options: {
    remarkPlugins: ["remark-gfm"],   // 표·취소선 지원
    rehypePlugins: ["rehype-slug"],  // 제목 앵커
  },
})

meta-Export statt Frontmatter

Üblicherweise schreibt man Titel und Datum in den ----Block (Frontmatter) am Anfang der Markdown-Datei. Da MDX aber JavaScript enthalten kann, gibt es einen saubereren Weg: einfach ein Objekt exportieren.

export const meta = {
  title: "글 제목",
  date: "2026-07-06",
  category: "dev",
}

## 본문 시작

Die Listenseite importiert jede Datei dynamisch und liest nur dieses meta aus.

const mod = await import(`@/content/posts/${slug}.mdx`)
return mod.meta   // 본문 렌더 없이 메타만

Keine Parsing-Bibliothek, kein separater Index nötig.

SEO von Anfang an

Wenn der Blog Besucher bringen soll, gehört SEO nicht ans Ende, sondern an den Anfang. Ich habe von Beginn an Metadaten pro Beitrag, Open Graph, strukturierte JSON-LD-Daten sowie sitemap.xml, robots.txt und rss.xml eingebaut. Dieses Thema behandle ich ausführlicher im nächsten Beitrag.

Fazit

  • Ein Beitrag ist eine .mdx-Datei, der Dateiname ist die URL
  • @next/mdx + Plugins als Strings (Turbopack)
  • export const meta statt Frontmatter
  • SEO ab dem ersten Commit

Mit genau dieser Struktur steht auch Ihr Blog in 30 Minuten. Ich sammle auf diese Weise weiter Geschichten zu meinen Produkten wie Welle des Tages.

Häufige Fragen

Warum MDX-Dateien statt eines CMS?

Die Beiträge werden zusammen mit dem Code versioniert, es kostet nichts, und Deployen heißt Veröffentlichen. Für Solo-Entwickler ist das der Weg mit der geringsten Reibung. Bilder, Code und Komponenten lassen sich außerdem frei einbetten.

Wie entsteht die Beitragsliste ohne Frontmatter?

Jede .mdx-Datei exportiert oben ein meta-Objekt. Die Listenseite importiert die Dateien dynamisch und liest nur dieses meta aus. Eine separate Parsing-Bibliothek ist nicht nötig.

Ähnliche Beiträge