Use Cases

So erstellen Sie ein Blog-CMS mit Claude Code

Erfahren Sie, wie Sie ein Blog-CMS mit Claude Code erstellen. Mit praktischen Codebeispielen und Schritt-für-Schritt-Anleitung.

Ein Blog-CMS mit Claude Code erstellen

Ein eigenes Blog-CMS zu haben gibt Ihnen vollständige Kontrolle über Design, SEO und Performance-Optimierung. Mit Claude Code können Sie ein CMS mit Artikelverwaltung, Vorschau und Veröffentlichungs-Workflow in kurzer Zeit aufbauen.

Prompt-Design

> Erstelle ein Blog-CMS mit Next.js App Router.
> Baue sowohl eine Verwaltungsoberfläche zum Erstellen, Bearbeiten und Veröffentlichen von Markdown-Artikeln als auch ein Frontend, das per SSG generiert wird.
> Implementiere auch Filterung nach Kategorien und Tags.

Artikeldatenmodell definieren

// src/types/post.ts
export interface Post {
  id: string;
  title: string;
  slug: string;
  content: string;        // Markdown
  excerpt: string;
  coverImage?: string;
  category: string;
  tags: string[];
  status: 'draft' | 'published' | 'archived';
  publishedAt?: Date;
  createdAt: Date;
  updatedAt: Date;
  authorId: string;
}

export interface PostCreateInput {
  title: string;
  content: string;
  category: string;
  tags: string[];
  status?: 'draft' | 'published';
}

Artikelverwaltungs-API implementieren

// src/app/api/posts/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
import { generateSlug } from '@/lib/utils';

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const category = searchParams.get('category');
  const tag = searchParams.get('tag');
  const status = searchParams.get('status') || 'published';

  const posts = await prisma.post.findMany({
    where: {
      status,
      ...(category && { category }),
      ...(tag && { tags: { has: tag } }),
    },
    orderBy: { publishedAt: 'desc' },
    select: {
      id: true,
      title: true,
      slug: true,
      excerpt: true,
      category: true,
      tags: true,
      publishedAt: true,
      coverImage: true,
    },
  });

  return NextResponse.json(posts);
}

export async function POST(request: NextRequest) {
  const body = await request.json();
  const slug = generateSlug(body.title);

  const post = await prisma.post.create({
    data: {
      ...body,
      slug,
      excerpt: body.content.substring(0, 160),
      publishedAt: body.status === 'published' ? new Date() : null,
    },
  });

  return NextResponse.json(post, { status: 201 });
}

Markdown-Editor-Komponente

// src/components/admin/MarkdownEditor.tsx
'use client';
import { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

interface Props {
  initialContent?: string;
  onSave: (content: string) => void;
}

export function MarkdownEditor({ initialContent = '', onSave }: Props) {
  const [content, setContent] = useState(initialContent);
  const [isPreview, setIsPreview] = useState(false);

  return (
    <div className="border rounded-lg">
      <div className="flex border-b">
        <button
          onClick={() => setIsPreview(false)}
          className={`px-4 py-2 ${!isPreview ? 'bg-blue-50 font-bold' : ''}`}
        >
          Bearbeiten
        </button>
        <button
          onClick={() => setIsPreview(true)}
          className={`px-4 py-2 ${isPreview ? 'bg-blue-50 font-bold' : ''}`}
        >
          Vorschau
        </button>
      </div>
      {isPreview ? (
        <div className="prose p-4 max-w-none">
          <ReactMarkdown remarkPlugins={[remarkGfm]}>{content}</ReactMarkdown>
        </div>
      ) : (
        <textarea
          value={content}
          onChange={(e) => setContent(e.target.value)}
          className="w-full h-96 p-4 font-mono text-sm resize-none"
          placeholder="Artikel in Markdown schreiben..."
        />
      )}
      <div className="flex justify-end p-3 border-t">
        <button
          onClick={() => onSave(content)}
          className="bg-blue-600 text-white px-6 py-2 rounded"
        >
          Speichern
        </button>
      </div>
    </div>
  );
}

Automatische SEO-Metadaten-Generierung

Wenn Sie Claude Code beauftragen, kann es auch die automatische OGP-Bildgenerierung und Meta-Tag-Konfiguration basierend auf dem Artikelinhalt implementieren.

// src/lib/seo.ts
export function generatePostMeta(post: Post) {
  return {
    title: `${post.title} | MeinBlog`,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      type: 'article',
      publishedTime: post.publishedAt?.toISOString(),
      tags: post.tags,
      images: post.coverImage ? [{ url: post.coverImage }] : [],
    },
  };
}

Verwandte Artikel

Für den Frontend-Teil der CMS-Erstellung ist der SSR/SSG-Vergleichsleitfaden hilfreich. Zur SEO-Optimierung siehe auch SEO-Optimierung.

Für die Auswahl von Markdown-Verarbeitungsbibliotheken bietet das unified.js-Ökosystem umfangreiche Referenzmaterialien.

#Claude Code #CMS #blog #Next.js #TypeScript