CMSをやめて気づいたのは、記事を書くことより、サイトを「維持する」ことの方がずっと大変だった、ということでした。
WordPressを使っていた頃、コーポレートサイトの更新は「ログインして書いて公開するだけ」のはずでした。ところが実際には、プラグインのセキュリティパッチが毎月来て、プラグイン間の互換性が壊れて記事一覧が崩れて、「コンテンツを書く人間」が「サイトを守る人間」を兼務していた。ぶっちゃけ、うちでは運用作業が後回しになりがちで、気づけばパッチの適用が2ヶ月遅れていたりしました。
そこで移行したのが、Astro + MDXによるGit管理構成です。これ自体はよくある話なんですが、もう一歩踏み込んで「誰が何をやるか」の役割分担を設計し直したのがポイントです。
役割を分けた
今の構成は、こういう分担になっています。
人間がやること:コンテンツを書く 記事はMDXファイルとして書き、GitHubにPRを出してマージされると公開されます。CMS時代と比べて、書く行為はシンプルになりました。管理画面もなければ、ログインする場所もない。
AIがやること:サイトを維持する 依存関係のアップデート確認、セキュリティパッチの検知と適用、壊れたリンクのチェック、デプロイパイプラインの問題検知——こういった「やらなければいけないが、手が回りにくい」作業群を、AIエージェント(Claude)がGitHub API経由でPRを作成してこなします。
最初は「本当に大丈夫か?」と思っていました。今思えば、この不安は「AIが自律的に何かをする」ことへの漠然とした恐怖だったんですが、実際にやってみるとAIがやっているのは「適切なPRを出す」ことだけで、マージするかどうかの判断は人間が持ったままです。
CLAUDE.mdという「業務規約」
AIに自由にリポジトリを触らせるのは怖い。なのでこのリポジトリには CLAUDE.md というファイルを置いて、AIが操作できるファイルの範囲・命名規則・禁止事項を明示しています。
## 操作が許可されているファイル
| ファイル | 操作内容 |
|-----------------------------------|------------|
| src/content/news/*.mdx | 作成・更新 |
## 操作が禁止されているファイル
| ファイル | 理由 |
|-----------------------------------|------------------------------|
| src/content/config.ts | スキーマ変更は破壊的影響がある |
| .github/workflows/*.yml | CI/CDパイプラインの改ざん防止 |
人間のチームメンバーに業務範囲を説明するのと同じ感覚です。スコープを文書化することで、AIが「これは触っていいのか?」を自分で判断できるようになる。ここは好みが分かれるところですが、この規約をリポジトリに含めて明示化しておく方が、後から「AIがどこを触れる権限を持っているか」を追跡しやすいと思っています。
GitHub API経由でPRを出す仕組み
AIがメンテナンス作業を行う場合、GitHub API経由でブランチを作ってファイルを変更し、PRを作成します。
await octokit.repos.createOrUpdateFileContents({
owner: 'your-org',
repo: 'your-repo',
path: `package.json`,
message: `chore: update dependencies (YYYY-MM-DD)`,
content: Buffer.from(updatedContent).toString('base64'),
branch: 'ai/deps-YYYY-MM-DD',
});
最初にこれを試したとき、ブランチを先に作るのを忘れてエラーになりました。「参照するブランチが存在しない」という当たり前のエラーなんですが、API越しだと気づきにくい。ブランチ作成→ファイル更新→PR作成の順番は守ってください。ドキュメントにはこう書いてあるけど、実際にやってみないと体感しにくいんですよね。
PRレビューが安全網になる
AIが出すPRには、変更ファイル一覧・変更の意図・確認事項のチェックリストが自動で入ります。人間がやることは、このPRを見て「問題ないか」を判断してマージするだけ。
最初は「AIが出したPRって品質大丈夫なの?」という不安がありました。今思えば、この不安を解消したのは技術的な工夫ではなく、「PRレビューがある」という構造そのものでした。どんな変更でも人間がチェックするフローが固定されていれば、意図しないものがそのまま本番に入る事故は起きない。
Zodスキーマが地味に助かっている
Astroのビルド時バリデーションも安全網になっています。
// src/content/config.ts — 変更禁止ファイル
const newsSchema = z.object({
title: z.string().max(100),
summary: z.string().max(200),
publishedAt: z.coerce.date(),
status: z.enum(['draft', 'published']),
tags: z.array(z.string()),
author: z.string(),
});
フロントマターに間違った値が入ると、ビルドが落ちてCIで止まります。改善の余地があるのも正直なところで、文字数や型の機械的な検証しかできていません。「内容が意味をなしているか」まではZodでは見られない。そこは人間のレビューで補う設計になっています。
振り返って
「コンテンツを書く人間」と「サイトを維持するAI」という役割分担は、思ったよりしっくりきています。人間はクリエイティブな作業に集中できる一方で、AIが定型的・反復的な運用作業をこなす。CMS時代に「全部やらなきゃいけない感」があったのとは、明確に違います。
「ログイン画面がなくなった」という変化も、意外と精神的な安心感がありました。攻撃対象が減るというのもあるし、「誰かに乗っ取られるかも」という漠然とした不安がなくなるのが大きい。
もっといい運用方法があれば、ぜひ教えてください。