How to Build a Blog CMS with Claude Code
Learn how to build a blog CMS using Claude Code. Includes practical code examples and step-by-step guidance.
Building a Blog CMS With Claude Code
Running your own blog CMS gives you complete control over design freedom, SEO, and performance optimization. With Claude Code, you can build a CMS that includes post management, preview, and a publishing workflow in a short time.
Prompt Design
> Build a blog CMS with Next.js App Router.
> Build both an admin UI for creating, editing, and publishing Markdown
> posts and an SSG-generated front-end.
> Also implement filtering by category and tag.
Defining the Post Data Model
// 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';
}
Implementing the Post Management API
// 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 });
}
A Markdown Editor Component
// 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' : ''}`}
>
Edit
</button>
<button
onClick={() => setIsPreview(true)}
className={`px-4 py-2 ${isPreview ? 'bg-blue-50 font-bold' : ''}`}
>
Preview
</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="Write your post in Markdown..."
/>
)}
<div className="flex justify-end p-3 border-t">
<button
onClick={() => onSave(content)}
className="bg-blue-600 text-white px-6 py-2 rounded"
>
Save
</button>
</div>
</div>
);
}
Automatic SEO Metadata Generation
If you ask Claude Code, you can also implement automatic OGP image generation and meta tag configuration based on the post content.
// src/lib/seo.ts
export function generatePostMeta(post: Post) {
return {
title: `${post.title} | MyBlog`,
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 }] : [],
},
};
}
Related Articles
For the front-end portion of your CMS, the SSR/SSG comparison guide is helpful. For SEO, also check out SEO optimization.
When picking a Markdown processing library, the unified.js ecosystem has a rich set of tools worth evaluating.
Level up your Claude Code workflow
50 battle-tested prompt templates you can copy-paste into Claude Code right now.
Free PDF: Claude Code Cheatsheet in 5 Minutes
Key commands, shortcuts, and prompt examples on a single printable page.
About the Author
Masa
Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.
Related Posts
How to Supercharge Your Side Projects with Claude Code [With Examples]
How to Supercharge Your Side Projects with Claude Code [With Examples]. A practical guide with code examples.
How to Automate Refactoring with Claude Code
Learn how to automate refactoring using Claude Code. Includes practical code examples and step-by-step guidance.
Complete CORS Configuration Guide with Claude Code
A complete CORS configuration guide using Claude Code. Practical tips and code examples included.