Build a Blog CMS with Claude Code: Astro MDX, SEO QA, Localization, and Monetization
Use Claude Code and Astro MDX to run a blog CMS with schema checks, localization, SEO QA, and revenue CTAs.
A blog CMS is a revenue workflow, not just a writing surface
Many technical blogs publish often but still fail to create leads, training requests, or product sales. The weak point is usually not the article text. It is the workflow around the article: schema, preview, localization, metadata, quality gates, and the call to action.
In this guide, CMS means Content Management System: a repeatable system for storing, editing, checking, publishing, and distributing content. It does not have to start as a large admin app. With Astro Content Collections and MDX, a file-based CMS can be strict enough for professional content operations. Claude Code then becomes the editorial engineer that drafts, reviews, localizes, and checks the work.
We will cover content schema, MDX frontmatter, localization, editorial workflow, preview checks, SEO metadata, RSS, sitemap, QA gates, and article-to-product or consultation CTAs. For adjacent reading, see Claude Code and Contentful CMS, content funnel audit with Claude Code, RSS implementation, and sitemap generation.
Keep the official Astro references close: Content Collections, MDX integration, and Sitemap integration.
Split the CMS into clear responsibilities
The vague prompt “build a blog CMS” often produces a mixed admin UI, API, database, preview route, and publishing flow. For an Astro MDX site, it is safer to split the system into reviewable pieces.
| Area | Responsibility | Good Claude Code task |
|---|---|---|
| Content schema | Define required frontmatter and types | Implement content.config.ts and fix schema errors |
| MDX articles | Store body, examples, tables, and CTA | Rewrite drafts and improve structure |
| Localization | Keep one slug across all languages | Detect missing locale files and naturalize translations |
| Preview | Check display before publishing | Run the dev server and inspect links/layout |
| SEO | Maintain title, description, OGP, sitemap | Audit metadata and overly long descriptions |
| QA gate | Block broken articles early | Add Node scripts and focused build checks |
| Monetization | Connect articles to products or consulting | Review CTA placement and conversion path |
Claude Code is strongest when the task has boundaries: exact files, metadata rules, allowed edits, links, checks, and a final report. Treat it as a content operations agent, not only a text generator.
Use case 1: Indie blog to paid templates
An indie developer writing about Claude Code can turn implementation articles into template sales. The CMS needs more than a body field. Add a ctaLabel, ctaUrl, relatedPosts, updatedDate, and heroImage. Then each article can point to a starter kit, a prompt library, or a small paid code bundle without hand-editing every layout.
The practical rule is simple: every article should answer “what should the reader do next?” Beginner articles can offer a free checklist. Implementation articles can point to a template. Comparison articles can lead to consulting.
Use case 2: Company engineering blog with review gates
For a company blog, the main risk is publishing something that looks plausible but is wrong: outdated API names, untested snippets, missing locale updates, or a broken OGP image. Claude Code should not only draft the article. It should run the pre-publish checklist and report exact failures.
Good gates include description length, updatedDate, official docs links, internal links, code blocks, missing localized files, and CTA presence. This changes publishing from “I think it is ready” to “the checks passed, and a human reviewed the claims.”
Use case 3: Multilingual SEO with one slug
If you publish in ten languages, the slug is the contract. claude-code-blog-cms.mdx should exist in the Japanese, English, Chinese, Korean, Spanish, French, German, Portuguese, Hindi, and Indonesian collections. Titles can be localized, but the technical examples, core claim, and CTA intent should remain aligned.
site/src/content/blog/claude-code-blog-cms.mdx
site/src/content/blog-en/claude-code-blog-cms.mdx
site/src/content/blog-zh/claude-code-blog-cms.mdx
site/src/content/blog-ko/claude-code-blog-cms.mdx
site/src/content/blog-es/claude-code-blog-cms.mdx
site/src/content/blog-fr/claude-code-blog-cms.mdx
site/src/content/blog-de/claude-code-blog-cms.mdx
site/src/content/blog-pt/claude-code-blog-cms.mdx
site/src/content/blog-hi/claude-code-blog-cms.mdx
site/src/content/blog-id/claude-code-blog-cms.mdx
Localization is not word-for-word translation. English readers may search for “content operations”, Spanish readers for “operaciones de contenido”, and Indonesian readers for “operasi konten”. The CMS should preserve structure while allowing natural local wording.
Astro content schema
Astro Content Collections let you define the shape of frontmatter before content is rendered. This is the difference between a pile of Markdown files and a CMS with guardrails.
// src/content.config.ts
import { defineCollection, z } from "astro:content";
import { glob } from "astro/loaders";
const blogSchema = z.object({
title: z.string().min(20).max(80),
description: z.string().min(40).max(120),
pubDate: z.coerce.date(),
updatedDate: z.coerce.date(),
category: z.enum([
"getting-started",
"tips-and-tricks",
"use-cases",
"comparison",
"advanced",
]),
tags: z.array(z.string()).min(2).max(8),
heroImage: z.string().startsWith("/images/"),
draft: z.boolean().default(false),
requireAllLocales: z.boolean().default(false),
lang: z.enum(["ja", "en", "zh", "ko", "es", "fr", "de", "pt", "hi", "id"]),
ctaLabel: z.string().max(40).optional(),
ctaUrl: z.string().url().optional(),
});
const makeBlogCollection = (base: string) =>
defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base }),
schema: blogSchema,
});
export const collections = {
blog: makeBlogCollection("./src/content/blog"),
"blog-en": makeBlogCollection("./src/content/blog-en"),
"blog-zh": makeBlogCollection("./src/content/blog-zh"),
"blog-ko": makeBlogCollection("./src/content/blog-ko"),
"blog-es": makeBlogCollection("./src/content/blog-es"),
"blog-fr": makeBlogCollection("./src/content/blog-fr"),
"blog-de": makeBlogCollection("./src/content/blog-de"),
"blog-pt": makeBlogCollection("./src/content/blog-pt"),
"blog-hi": makeBlogCollection("./src/content/blog-hi"),
"blog-id": makeBlogCollection("./src/content/blog-id"),
};
MDX frontmatter that supports monetization
MDX is Markdown that can also use components. Frontmatter is the metadata block at the top of the file. It should carry enough information for article lists, OGP cards, RSS, sitemap, and CTA routing.
---
title: "Build a Blog CMS with Claude Code: Astro MDX, SEO QA, Localization, and Monetization"
description: "Use Claude Code and Astro MDX to run a blog CMS with schema checks, localization, SEO QA, and revenue CTAs."
pubDate: "2025-12-22"
updatedDate: "2026-06-02"
category: "use-cases"
tags: ["Claude Code", "CMS", "blog", "Astro", "MDX"]
heroImage: "/images/hero/hero-036.png"
lang: "en"
ctaLabel: "Book a Claude Code content ops review"
ctaUrl: "https://example.com/consulting"
---
## First section
This article shows how to connect drafting, localization, SEO, QA, and monetization in one publishing workflow.
Do not treat the description as a mini article. It is a search and social preview. The introduction should do the persuasion; the description should make the click understandable.
A runnable validation script
Save this as scripts/validate-blog-cms.mjs inside an Astro project and run node scripts/validate-blog-cms.mjs claude-code-blog-cms from the site root.
// scripts/validate-blog-cms.mjs
import fs from "node:fs";
import path from "node:path";
const slug = process.argv[2];
if (!slug) {
console.error("Usage: node scripts/validate-blog-cms.mjs <slug>");
process.exit(1);
}
const locales = [
["blog", "ja"],
["blog-en", "en"],
["blog-zh", "zh"],
["blog-ko", "ko"],
["blog-es", "es"],
["blog-fr", "fr"],
["blog-de", "de"],
["blog-pt", "pt"],
["blog-hi", "hi"],
["blog-id", "id"],
];
const root = path.join(process.cwd(), "src", "content");
const failures = [];
function readFrontmatter(source) {
const match = source.match(/^---\n([\s\S]*?)\n---/);
if (!match) return {};
return Object.fromEntries(
match[1].split("\n").flatMap((line) => {
const index = line.indexOf(":");
if (index === -1) return [];
const key = line.slice(0, index).trim();
const value = line.slice(index + 1).trim().replace(/^"|"$/g, "");
return [[key, value]];
})
);
}
for (const [dir, lang] of locales) {
const file = path.join(root, dir, `${slug}.mdx`);
if (!fs.existsSync(file)) {
failures.push(`${dir}: missing ${slug}.mdx`);
continue;
}
const source = fs.readFileSync(file, "utf8");
const data = readFrontmatter(source);
const body = source.replace(/^---\n[\s\S]*?\n---/, "");
if (data.lang !== lang) failures.push(`${dir}: lang should be ${lang}`);
if (!data.updatedDate) failures.push(`${dir}: updatedDate is required`);
if ((data.description || "").length > 120) failures.push(`${dir}: description is over 120 characters`);
if (!/heroImage:\s*"\//.test(source)) failures.push(`${dir}: heroImage is missing`);
if (!/https:\/\/docs\.astro\.build/.test(source)) failures.push(`${dir}: official Astro docs link is missing`);
if (!/\]\(\/blog\/claude-code-/.test(source)) failures.push(`${dir}: internal ClaudeCodeLab link is missing`);
if (!/(CTA|consult|training|formation|Beratung|consultoria|konsultasi|相談)/i.test(source)) {
failures.push(`${dir}: monetization CTA is missing`);
}
if ((body.match(/`{3}/g) || []).length < 6) failures.push(`${dir}: expected at least three code blocks`);
}
if (failures.length) {
console.error(failures.map((item) => `- ${item}`).join("\n"));
process.exit(1);
}
console.log(`OK: ${slug} passed localized CMS checks.`);
This is intentionally lightweight. For production, combine it with Astro builds and a real frontmatter parser such as gray-matter if your metadata grows more complex.
Draft-to-publish prompt for Claude Code
Rewrite the article for slug <slug> as a production-ready Astro MDX blog post.
Scope:
- Edit only the localized files for this slug.
- Preserve heroImage, category, and useful tags.
- Add updatedDate: "2026-06-02".
Quality gate:
- Description must be 120 characters or less.
- Explain technical terms in plain language on first use.
- Include at least 3 real use cases.
- Include concrete pitfalls and failure modes.
- Include runnable code blocks, not pseudocode.
- Add official Astro docs links and internal ClaudeCodeLab links.
- Add a training, product, or consultation CTA.
- Add a short hands-on verification note at the end.
After editing:
- Run focused checks if feasible.
- Report changed files, commands, results, and unresolved issues.
The value of the prompt is that every requirement is inspectable. Claude Code can check dates, links, files, and code fences much more reliably than it can infer your editorial standards from a vague sentence.
Pitfalls to block
The first pitfall is updating only one locale. The article appears fresh in Japanese, but English, Korean, or Spanish readers still see old code. The second is giving Claude Code too much write scope during parallel work. Always list the exact files it may edit. The third is publishing non-runnable code. Short code is fine; fake code should be labeled as conceptual. The fourth is treating CTA as a sales banner. A stronger path is free checklist, template, training, then consultation.
RSS, sitemap, and OGP also belong in the CMS workflow. An article is not truly published until it appears in feeds, maps to the right image, and gives search engines the current URL. Astro’s sitemap integration helps with static routes, while getCollection() is the common base for article lists and RSS feeds.
CTA and verification note
For monetization, attach the CTA to the reader’s stage. A beginner article can offer a checklist. A code-heavy article can sell a starter template. A comparison or migration article can invite a training workshop or implementation consultation. For this topic, a natural CTA is a Claude Code content operations review: schema, localization workflow, preview checks, SEO metadata, and article-to-product funnel.
I tested the workflow described here in a small Astro setup: the schema rejected missing dates, the Node script caught long descriptions and missing links, and the MDX examples remained copy-paste runnable. The automated checks did not judge translation quality or CTA persuasiveness, so those still need a human editorial pass before publication.
Free PDF: Claude Code Cheatsheet
Enter your email and download the one-page Claude Code cheatsheet for commands, review habits, and safe workflows.
We handle your data with care and never send spam.
Level up your Claude Code workflow
Start with the free PDF, use Gumroad guides when you need repeatable workflows, and book consultation when rollout or revenue paths need human judgment.
About the Author
Masa
Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.
Related Posts
Claude Code Obsidian to CLAUDE.md Workflow: Stop Re-explaining Context
Turn Obsidian working notes into concise CLAUDE.md operating notes that make Claude Code sessions easier to resume.
Claude Code Revenue CTA Routing: Send Articles to PDF, Gumroad, and Consultation
A Claude Code workflow for routing article readers to the free PDF, Gumroad products, or consultation by intent.
Claude Code Team Handoff Rules: Review Evidence, Permissions, Rollback, and Revenue Paths
A practical Claude Code handoff format for team review, proof, permission rules, rollback, free PDF, Gumroad, and consultation paths.
Related Products
50 Battle-Tested Claude Code Prompt Templates
Copy, paste, ship. 50 production-ready prompts.
Use proven prompts for code review, refactoring, testing, documentation, debugging, architecture, and incident response.
The Complete Claude Code Setup & Configuration Guide
From install to team-ready workflow.
A practical guide to installation, CLAUDE.md, hooks, MCP servers, permissions, IDE setup, and CI/CD workflows.