リモート開発メインのソフトウェア開発企業のエンジニアブログです

AI + Sveltia CMS でまとめサイトを作る一つの方法

目次

もばらぶでは比較的海外在住メンバーが多いのもあって、海外移住してる人・したい人向けのオンラインコミュニティ Mo-Mado を運営しています。(最近、Mo-Mado に関するブログ投稿が途絶えていますが、コミュニティ自体は活発に活動しています。)興味のある方は以下のリンクより参加してください。

Join Mo-Mado on Slack | Slack

さて本題ですが、海外移住やビザに関するニュースを集めた「まとめサイト」を、AI + Sveltia CMS というツールを使って半自動で作ったので、その方法を紹介します。

大まかな仕組み

出力は2つ: Slack のニュース配信チャンネルとまとめサイト

まとめサイトを作ったと書きましたが、実際には情報の配信先は

  • Slack のニュース配信チャンネル
  • まとめサイト

の2つです。前者は比較的短文で概要だけ載せ、後者に詳しい情報を載せるという形です。

Slack 投稿の例はこんな感じです。

まとめサイトの記事は以下のようなものです。

タイのDTVビザ、2026年8月31日から申請要件を厳格化 無犯罪証明書が必須に | Mo-Mado Articles

ワークフロー

まずはワークフローを説明します。

  1. AI エージェントが1日1回ネットからニュース記事を拾う
  2. AI エージェントが拾ってきた記事を元に投稿案を作成し、Slack の管理者用チャンネル1に投げる
  3. 人間がそれを見て、以下を Slack のスレッドに返信する
    • OK -> Slack 投稿だけ
    • OK article -> Slack 投稿+まとめサイト記事化
    • NG -> 採用せず
    • フリーテキスト -> 修正依頼
  4. ボット1がそれを読み、OK なら Slack のニュース配信チャンネルに記事を投稿する
  5. OK article なら、4に加えて Slack の管理用チャンネル2にメッセージを投げる
  6. ボット2が Slack 管理用チャンネル2のメッセージを読んで、それを元にブログの下書き投稿を作成する
  7. ボット2が5のメッセージのスレッドに、記事編集画面の URL と共に下書き作成完了した旨の返信をする
  8. 人間がそれを見て、記事編集画面で直接記事を編集するか、Slack の返信で修正依頼を送る
  9. 下書きを公開したい場合、記事編集画面で直接操作するか、Slack で OK や publish 等の返信をする

というものです。

本ブログの熱心な読者(社員以外でいるかどうかは不明)ならお気づきかもしれませんが、前半部分のワークフローは以下の記事で紹介した内容です。

Cloudflare Workflows で Human-in-the-loop を実装する – もばらぶエンジニアブログ

今回、上のワークフローの5〜9を追加したという形です。5は前回のワークフローの改修、6〜9は新規作成です。

ちなみに、前半部分(1〜5)と後半部分(6〜9)のワークフローは疎結合になっています。GitHub レポジトリー、Cloudflare Worker、Slack チャンネルなどは全て分かれています。ただし、Slack アプリだけは同じものを使っています。

アーキテクチャ

HITL の基本的な仕組みは前回の記事と同じですが、上述のワークフロー7〜9の記事編集周りが前回とは異なります。

今回使っているのは以下のものです。

Sveltia CMS — Free, open source, Git-based headless CMS

Sveltia CMS についての解説

概要

Sveltia CMS 今回の仕組みを作るにあたり AI から提案されて初めて知ったのですが、

  • headless
  • Git ベース

の特徴を持つ CMS です。

headless とは、大雑把に言って記事作成・編集画面などのコンテンツ管理(backend・body)のみを提供し、実際の記事を表示する部分(frontend・head)はないものを意味します。WordPress 等の従来型の CMS はコンテンツ管理部分とコンテンツ表示部分が一体化していますが、headless の場合は body のみで head は別の仕組みに任せます。

また、Git ベースですが、記事等のコンテンツ作成・編集それぞれが Git のコミットとして保存されます。

バックエンド

Sveltia CMS は Git ベースと書きましたが、バックエンドとして以下の3つが使えます。

  • GitHub
  • GitLab
  • Gitea/Forgejo

最初の2つは知っていますが、3つ目は知らなかったので調べたところ、セルフホスト可能な Git サービスだそうです。(大昔に Gitorious というのを使った事がありますが、コンセプトとしては似たような感じのようです。)

今回は GitHub を使うので、以降はそれ前提で話します。

まず必要なものはレポジトリーです。Sveltia CMS で内容を編集して「Save」ボタンを押すと、そのレポジトリーに対するコミットとして登録されます。

認証・認可

GitHub バックエンドの場合、Sveltia CMS の認証・認可は以下の2通りが使えます。

  • Personal Access Token (PAT)
  • OAuth

手軽に始めるのであれば PAT が良いのですが、今回は非技術者が使うことなども想定して OAuth にしました。非技術者であっても GitHub アカウントの作成くらいは出来ますが、PAT、特に fine-grained token の作成は若干ハードルが高いですし、UX としても良くないためです。

編集の流れ: 直コミット vs. PR ベース

記事の作成・編集を PR にして、別の人がそれをチェックしてマージすると公開されるというフローにも出来るようですが、まずはスモールスタートと言うことで記事の変更などは全て main ブランチにコミットされるようにしました。

実際の構成

前置きが大分長くなりましたが、まずは構成を説明していきます。大まかにボット部分とサイト部分の2つに分かれます。

ボット部分

Slack の管理用チャンネル2にメッセージ到着
        │ Slack 側で Event Subscriptions の設定(※2)
        ▼
前回作成の Worker1 (/slack/events) … 署名検証 → 管理用チャンネル2のメッセージの場合は転送
        │ 
        ▼
今回作成の Worker2 (/slack/events) … 署名検証 → メッセージ分類
        │ 
        ▼
メッセージ種別に応じた実際の処理
1. 前回作成のボットからの記事作成依頼 → 記事草稿作成 → スレッドへ結果を返信
2. 人間からの返信 → OK なら公開、修正依頼なら草稿を修正、いずれに場合もスレッドへ返信
3. 今回のボット自身のメッセージ → 無視Code language: JavaScript (javascript)
  • ※1: 「ボット」と大雑把に書いていますが、実体は Cloudflare Workflow などです。
  • ※2: Slack の Event Subscriptions は1つの URL しか指定できないため、前回作成した Worker がルーティングの役割も担っています。

サイト部分

使っているのは以下のものです。

  • 表示部分: Astro
  • CMS 部分: Sveltia CMS

ディレクトリ構成は大まかに以下の通りです。

  • site/ → この下は基本的には Astro のファイル
    • public/admin/ → ここに Sveltia CMS のファイルを置く
    • src/
      • assets/, components/ など、通常のファイル
      • content/posts/ → Sveltia CMS が作成する Markdown ファイル

認証・認可に OAuth を使うと最初の方に書きましたが、そのためには以下のレポジトリーを「Deploy to Cloudflare」ボタンで Cloudflare にデプロイする必要があります。

sveltia/sveltia-cms-auth: Cloudflare Workers script that allows Sveltia CMS users to authenticate with GitHub.

本記事を書いていて思いましたが、それなりに複雑な仕組みになっています。ただ、AI だと割とすんなり実装出来てしまうのが凄いと思いました(月並み)。

Moba Pro

設定等

長くなったので要点のみ書きます。

Slack アプリ

Slack への書き込み、Slack への投稿の読み込みのためには Slack アプリが必要です。私は、前回の仕組みで作った Slack アプリを使い回しました。Slack のアプリ管理画面で主にやる事は

  • 権限の設定(チャンネルへの読み書き等)
  • Event Subscriptions の設定(Slack -> Cloudflare への通知)

くらいかと思います。

ボットプログラム(Cloudflare Worker)

プログラムの詳細は省略しますが、このプログラムでやる事は主に

  • Slack チャンネルの投稿を読み込んで、それをトリガーに記事の作成、修正を行う
    • 記事の作成・編集はコンテナー内で実行する Claude Code が行う
  • Slack チャンネルに結果の通知をする

といったものです。

設定としては以下の環境変数を設定します。

  • SLACK_SIGNING_SECRET -> Slack メッセージの検証のため必要
  • BLOQUE_API_KEY -> Slack MCP サーバー等、MCP サーバーは Bloque 経由で使っているので
  • GITHUB_TOKEN -> GitHub の PAT。記事を保存する レポジトリーへの読み書き権限が必要
  • ANTHROPIC_API_KEY か CLAUDE_CODE_OAUTH_TOKEN -> Claude Code を使うため

Sveltia CMS Authenticator

Sveltia CMS で GitHub ログインをするために必要なものです。

Deploy to Cloudflare ボタンを押して Cloudflare にデプロイできます。

Sveltia CMS Authenticator で使うための GitHub OAuth App を作っておく必要があります。また、Cloudflare のワーカーに以下の環境変数を設定しておく必要があります。

  • GITHUB_CLIENT_ID
  • GITHUB_CLIENT_SECRET
  • ALLOWED_DOMAINS

Sveltia CMS

特別な設定はないです。

感想等

良い仕組みが出来たなと、全般的には満足しています。

サイト自体は Astro がビルドしたものなので軽い

会社ではそれなりの数の WordPress サイトを運用しています。高機能なプラグイン(WooCommerce 等)が必要なサイトであれば WordPress も良い選択肢だと思いますが、単純に記事を書きたいだけであれば WordPress は無駄が多いなと最近は思うようになりました。

今回のようにヘッドレス構成であれば、サイト表示は他のフレームワークに任せることが出来ます。今回は CMS 部分を Sveltia CMS にして、サイト表示部分は Astro を使っています。Cloudflare 上にデプロイしていますが、非常に軽快に動作するので気に入っています。

(余談ですが、本エンジニアブログも、CMS としては WordPress を使っていますが、表示部分は Netlify にデプロイした Next.js です。)

Git ベースなので編集履歴が追いやすくて良い

Sveltia CMS は機能は限定的ですが、作成されるファイルは Markdown で GitHub に変更がコミットされるため、編集履歴が追いやすくて良いです。

GitHub ログイン(OAuth)により、非技術者でも使える

GitHub ベースとなると非技術者には使えない仕組みになりがちですが、Sveltia CMS Authenticator により OAuth が使えるため、一度設定してしまえば、非技術者でも記事の作成・編集が出来ます。

現在は私一人が記事の編集を行っていますが、そのうち誰かに引き継ごうと思います。

AI で ChatOps が簡単に実現できる世の中になった

今までも業務の多くをチャットに集約している技術系企業はそれなりにありました。便利そうだなーと思う反面、実装が面倒くさいので手を付けずにいました。私はエンジニアとしてそれなりに経験がありますがそれでも面倒くさいと思っていたので、初〜中級くらいの人だと尚更そうだと思います。

それが今では、コンセプトや設計方針などを理解しておけば短時間で今回のようなチャットベースの仕組みが実現できます。今回の仕組みも空いた時間にちまちまやって1週間かからないくらいで実現できました。

全自動で AI が作るのではなく人間の目が入るので、それなりに質は担保出来る

ネットのニュースを自動的に拾って全自動でサイトを作るというのは、今では簡単にできます。5〜10年前は人力(※)でまとめサイトを作るというのが SEO の一環として行われてきましたが、今はコストはほぼゼロで同じ事が出来ます。

※: 1文字1円とか、1記事数千円とか

ただ、完全に自動化してしまうとゴミのようなサイトが出来てしまうため、ある程度人の目で選別した方が良いと考えています。今回の仕組みでは以下のような形で人間が介在しています。

  • どのニュースソースを記事化するか、人間が選別する
  • AI が書いた草稿に対して、人間が修正依頼を出す
  • 作成された記事に、人間の意見を手動で追記する

現在は3記事だけですが、今後は記事数を徐々に増やすとともに整理してしていき、有用なサイトにしていきたいと思っています。

改善点等

ワークフローが複雑になった場合の対応

現在は、前回のもの↓と今回のものの2つのワークフローが連携しているだけの比較的シンプルなものです。

Cloudflare Workflows で Human-in-the-loop を実装する – もばらぶエンジニアブログ

ここに承認フローを組み込んだり、他のサイト・SNS との連携とかが加わると、現在どこまで進んでいるのかとかが分かりにくくなってくると思います。

n8n などで管理してみるのも一つの方法だと考えています。

コンテンツの整理・UI の改善

タグ・カテゴリーを整理して、メニューとかも分かりやすくしようと思います。技術的には簡単なので、詳しくは書きません。

過去の指摘事項から学習する

今回は紹介していないものの今も一部は実装済みなのですが、記事の修正依頼を保存しておいて、次回以降の記事作成時に参照するという形にしたいです。それにより、同じ指摘事項を何度もする必要はなくなります。

ニュースソースの追加: Slack でのやり取りや X での話題

現在はネット(ウェブサイト)の情報を拾ってきて、それを解説した記事を作成しているのですが、今後はネタ元を増やしたいです。

  • Mo-Mado の Slack チャンネルでの会話のうち有用なものを個人情報などは取り除いた形で
  • X で話題となっている投稿

などです。

汎用化・横展開

後は、この仕組みを汎用化して他の分野でも使ってみたいと考えています。

まとめ

以前は人力で作成していたまとめサイトが現在は AI を使って自動的に作ることが出来ます。ただ、全自動にすると質の担保が難しいため、人間が介在する仕組みを構築しました。具体的には、ボットが Slack 上で作成内容を提案し、人間が Slack 上で修正依頼を出したり、編集画面で直接修正したりする仕組みです。これにより、AI による自動化と人間による判断のいいとこ取りができたと思います。

技術的には、コンテンツ作成部分は Sveltia CMS という GitHub ベースの headless CMS を使っており、Slack ベースのチャットボットは Cloudflare Worker 上で実装されています。また、記事の作成・編集を行う AI は、コンテナ上で実行される Claude Code が担当しています。

今後は、今回の仕組みの改善を行うと共に、他のサイトにも横展開したいと考えています。

← 前の投稿

次の投稿 →

Dify と n8n を同じサーバー、違うホスト名で動かす

コメントを残す