Von Directus zu MDX: Meine Website-Evolution
12. September 2025
Eine Reise von komplexer CMS-Architektur zu eleganter Einfachheit - wie ich meine Website von Directus/PostgreSQL auf reines MDX umgestellt habe.
Inhalte
Nach monatelanger Entwicklung und ständiger Verkomplizierung meiner persönlichen Website habe ich einen radikalen Schritt gewagt: Komplette Vereinfachung. Hier ist die Geschichte meiner technischen Reise und warum weniger manchmal definitiv mehr ist.
🏗️ Die ursprüngliche Architektur
Meine Website startete als ambitioniertes Full-Stack-Projekt:
Was ich ursprünglich hatte:
- Backend: PostgreSQL 16 mit Drizzle ORM
- CMS: Directus für Content-Management
- Admin-Panel: Selbstgebaute Admin-Oberfläche mit Live-Preview
- Komponenten-System: Datenbankgesteuerte Komponenten-Registry
- API-Layer: RESTful Routes für alle Inhalte
- Authentication: Token-basiertes Admin-System
- Deployment: Docker Compose mit mehreren Services
Das Problem
Was als "professionelle Lösung" begann, wurde schnell zu einem Wartungsalbtraum:
# Typischer Development-Start
docker compose up -d # Postgres + Directus starten
npm run drizzle:migrate # Schema-Migration
npm run components:push # Komponenten synchronisieren
npm run drizzle:studio # GUI für Debugging
npm run dev # Endlich: Development Server
4-5 Schritte nur um zu entwickeln. Jedes Mal.
🤔 Der Wendepunkt
Der Moment der Wahrheit kam, als ich merkte:
- 90% meiner Zeit ging für Infrastructure drauf
- 10% für tatsächlichen Content
- Ich schrieb mehr Migrations als Blogposts
- Setup-Zeit > Schreibzeit
⚡ Die neue Architektur: Radikal vereinfacht
Current Tech Stack (2025):
// Das ist mein ganzer "CMS":
interface BlogPost {
title: string;
date: string;
excerpt: string;
tags: string[];
published: boolean;
}
Mein neuer Stack:
- Framework: Next.js 15 mit App Router & React 19
- Content: MDX-Dateien mit Frontmatter
- Styling: Tailwind CSS 4
- Deployment: Single Docker Container
- Database: ❌ Keine!
📝 Content Creation: Vorher vs. Nachher
Vorher (Directus):
- Admin-Panel öffnen
- "Neuer Post" klicken
- Felder ausfüllen
- Content in Textarea schreiben
- Speichern & Veröffentlichen
- Hoffen, dass alles funktioniert
Jetzt (MDX):
---
title: "Mein neuer Post"
date: "2025-01-12"
published: true
---
# Content direkt hier schreiben!
Mit **IntelliSense**, **Syntax-Highlighting** und **Git-Versionierung**.
Ein File. Fertig.
🚀 Die Vorteile des MDX-Ansatzes
1. Developer Experience
# Neuer Blogpost?
touch content/blog/mein-post.mdx
code content/blog/mein-post.mdx
# Deployment?
git push
2. Performance
- No Database Queries: Alles statisch generiert
- Fast Builds: Turbopack + keine DB-Abhängigkeiten
- CDN-Ready: Perfekt für statisches Hosting
3. Flexibilität
# Ich kann direkt React-Komponenten einbauen:
<div className="bg-gradient-to-r from-blue-500 to-purple-600 p-4 rounded">
Styled Content direkt im Markdown!
</div>
# Oder Mathematik:
$$
E = mc^2
$$
4. Versionierung
Jeder Blogpost hat Git History. Rollbacks, Diffs, Branches - alles da.
🔧 Technical Deep Dive
Blog-System Implementation:
// /src/lib/blog.ts
export function getAllBlogPosts(): BlogPost[] {
const slugs = getAllBlogSlugs();
return slugs
.map((slug) => getBlogPostBySlug(slug))
.filter((post): post is BlogPost => post !== null)
.filter((post) => post.published)
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
}
26 Zeilen Code ersetzen eine komplette CMS-Database.
Deployment:
# Dockerfile (vereinfacht)
FROM node:20-alpine AS builder
COPY . .
RUN npm ci && npm run build
FROM node:20-alpine AS runner
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/content ./content
CMD ["node", "server.js"]
Ein Container. Ein Command. Es funktioniert einfach.
📊 Vorher vs. Nachher Vergleich
Aspekt | Directus + DB | MDX Static |
---|---|---|
Setup-Zeit | 5-10 Minuten | 30 Sekunden |
Dependencies | 15+ Services | 0 Services |
Build-Zeit | 3-5 Minuten | 30-60 Sekunden |
Deployment | Docker Compose | Single Container |
Backup | DB Dumps + Files | Git Repository |
Rollback | Complex | git revert |
Offline-Arbeit | Unmöglich | Problemlos |
🎯 Lessons Learned
1. Premature Optimization ist real
Ich baute für 1000 Posts, als ich 3 Posts hatte.
2. Developer Experience > Architecture Porn
Elegante Architektur nützt nichts, wenn sie mich vom Schreiben abhält.
3. Static is the new Dynamic
99% meiner "dynamischen" Inhalte waren eigentlich statisch.
4. Git is a CMS
Warum ein CMS bauen, wenn Git schon perfekt ist?
🔮 Zukunftspläne
Was bleibt:
- MDX für Content
- Next.js für Framework
- Tailwind für Styling
- Simplicity als Grundprinzip
Was kommt:
- Bessere MDX-Komponenten für interaktive Inhalte
- Automatisierte Builds bei Git-Push
- CDN-Integration für globale Performance
- Vielleicht ein einfaches Admin-Interface (aber nur wenn nötig!)
💡 Fazit: Weniger ist mehr
Diese Migration hat mir gezeigt: Komplexität ist ein Feature, das niemand braucht.
Meine Website ist jetzt:
- ⚡ Schneller zu entwickeln
- 🛡️ Zuverlässiger im Deployment
- 🔧 Einfacher zu warten
- 📝 Angenehmer für Content-Creation
Der beste Code ist der, den du nicht schreiben musst.
🤓 Tech-Details für Interessierte
Vollständiger Stack:
{
"framework": "Next.js 15",
"runtime": "React 19",
"language": "TypeScript (strict)",
"styling": "Tailwind CSS 4",
"content": "MDX + gray-matter",
"math": "KaTeX",
"markdown": "remark-gfm",
"deployment": "Docker + Coolify",
"hosting": "Static Generation"
}
Repository-Struktur:
├── content/blog/ # MDX blog posts
├── src/
│ ├── app/ # Next.js app router
│ ├── components/ # React components
│ ├── lib/ # Blog utilities
│ └── styles/ # Global CSS
├── Dockerfile # Single-container deploy
└── DEPLOY.md # Simple deployment guide
Weniger Dateien, weniger Komplexität, mehr Focus auf das was wirklich zählt: Content.
Happy Coding! 🚀