Article by:
CMS統合AIを使わず、なぜカスタム構築にしたのか。
- 依存ゼロ:コンテンツはリポジトリに置かれます。APIの障害がなければビルドの失敗もありません。
- スキーマの制限なし:Frontmatterで構造を自分たちで定義します。新しいフィールドやスキーマタイプが必要になれば、追加するだけです。サブスクリプションの制限も、プランの縛りもありません。
- 「Sentryらしい」やり方:深い技術志向を持つデベロッパーファーストの企業として、コンテンツをコードとして管理することは自然な選択です。バージョン管理され、ピアレビューされ、レンダリングするコンポーネントのすぐそばに置かれます。
実施プロセス
マーケティングサイトとブログ合わせて約2,500ページのサイトを移行するのは、大規模なプロジェクトです。チームは2.5人の開発者で、期間は2か月でした。
チームが小さく、サイトの規模が大きかったため、コーディングの多くをClaude Codeに頼りました。開発者たちは計画立案、スコープ定義、要件整理に時間の大半を費やし、コードのレビュー、変更の指示、アウトプットの調整を行いました。
スコープ定義
このプロジェクトでは、次の2つの理由からスコープ定義が比較的容易でした。
- これらのWebサイトにはモノレポを使用しているため、ボットがビルド・移行対象の全体像を把握できていた。
- 新規のデザインを実装しなかった。
既存のコードベースで数年間作業してきたこともあり、コードの肥大化を除去できそうな箇所についてのアイデアはありました。特定のディレクトリ内のページを詳しく調べてそれを検証し、コンテンツの内容に基づいて独自ページをテンプレートに統合して削減しました。その結果、約200ページを3つのテンプレートに集約でき、サイトがDRYになり、保守がはるかに容易になりました。
ボットを使ったビルド
まずデータから着手しました。ヘッドレスCMSはGatsbyサイトとAstroサイトの既存部分の両方に接続されており、CMSは各スキーマのJSONファイルを提供していました。そこで計画エージェントに既存のCMSスキーマを渡し、Frontmatterとして複製させました。すでにCMSのAPIに接続していたため、エージェントスウォームにデータを取得させ、Frontmatterファイルにマッピングし、画像をローカルに保存させました。画像最適化が必要な非メタ画像はすべて asset として、SEO画像は public ディレクトリに保存しています。
データが揃った後、計画エージェントにGatsby内の既存テンプレートファイルの場所、新フレームワーク内での配置先、使用するデータを伝え、不明な点があればインタビューするよう依頼しました。計画エージェントはビルドテストを汎用エージェントに渡し、そのエージェントがテスト用の汎用エージェントへと引き継ぎました。
そのラウンドの後、チームがリグレッションをレビューして修正し、SentryのSeer AIコードレビューツールとCursorのBugbot(シークレットスキャンや標準自動テストを含むリポジトリの品質チェックと合わせて)によるAI PRレビューが続きました。
ボットを使ったテスト
開発プロセスの一環として、Playwrightによるビジュアルリグレッションテストとチームが自作したMCPをClaude Codeで動かし、GatsbyサイトとAstroの新サイトのビジュアル要素を比較する実験を行いました。
DOM InspectorのMCP
チームのDylan Cootsが構築したDOM Inspector MCPは、Puppeteer(ヘッドレスChrome)を使ってローカルの開発サーバーに接続し、ページ上の要素をプログラムで検査・計測・操作します。スペースのずれや要素のサイズ、算出されたスタイルといったUIレイアウトの問題を検出し、ボットに修正させることを目的に設計されました。
コアアーキテクチャ
DOMInspectorクラス:Puppeteerのブラウザ・ページのライフサイクルを管理する中心的なオブジェクトです。完全に自前でブラウザを起動するモードと、静的ファクトリメソッドfromPage()で外部のページを受け取るセッション管理モードの2つがあります。- ブラウザ管理:メモリ制限フラグ(
--max-old-space-size=256、レンダラープロセス数の制限)を指定してヘッドレスChromeを起動し、5秒のタイムアウト後にPIDでプロセスを強制終了するグレースフルシャットダウンを処理します。 - DOM検査メソッド:
inspectElement()(寸法と算出CSS)、measureDistance()(2要素間のピクセル/rem単位のギャップと、それを生み出しているCSSプロパティ)、measureLayoutShift()(ページをリロードして遷移前後の要素位置を差分比較)、debugPage()(セレクターが見つからない場合にDOMをスキャンして一般的なコンポーネントパターンを探す)を含みます。 - インタラクションとナビゲーション:
interactWithElement()はセレクターをクリックして前後の状態を計測し、navigateToUrl()は新しいURLに遷移して古いコンソールログをクリアし、setViewport()は名前付きプリセット(mobile/tablet/desktop/large)または任意のピクセル幅と自動計算された高さをサポートします。 - ユーティリティメソッド:
screenshot()(ページ全体またはセレクター単位のスクリーンショット、base64で返却)、evaluateJs()(ページコンテキストで任意の非同期JSを実行)、waitForSelector()、getPageContent()(テキスト/HTML/outerHTMLを切り詰め対応で取得)、getConsoleLogs()(バッファリング済み、500エントリ上限)を含みます。 - CLIエントリーポイント:
main()はファイルが直接実行された場合のみ動作し(require()経由では不可)、--urlと--portフラグを受け取り、ハードコードされたコンポーネント(.WhoSentYouWrapper)のクイック検査をスモークテストとして実行します。 extractUrlFromText():クラスと一緒にエクスポートされるヘルパー関数で、自然言語の文字列からlocalhostのURLを解析します。ユーザーのテキストプロンプトを受け取るMCPサーバーから呼び出されることを想定した設計です。
うまくいったこと
PlaywrightのビジュアルリグレッションテストとDOM Inspector MCPは、組み合わせて使うと最も効果的でした。ビジュアルテストのワークフローは、各テンプレートのPlaywrightテストでビジュアルリグレッションを検出することから始まります。その結果を別のエージェントに渡して修正し、次にDOM Inspector MCPでPlaywrightのテスト修正後も残った要素レベルの問題を細かく調整しました。DOM Inspectorは要素単位の細かい検査において、より精度が高いことが分かりました。それでも100%ではありませんでしたが、面倒なスタイル修正にかかる時間を節約することができました。
コンテンツの更新(こちらもボットで)
CMSでのコンテンツ更新は手間がかかるため、Frontmatterやコードの深い知識がなくてもコンテンツを更新できるよう、いくつかのClaude Skillsを作成しました。
コマンドライン向けスキル
非開発者にとって、git操作(あるいはターミナル自体)は敷居が高いものです。しかし品質と一貫性のためにPRベースのワークフローに価値があると考え、これを助けるユーティリティスキルを作成しました。
/new-branch:originのmainブランチを最新の状態に更新して回避可能なマージコンフリクトを防ぎ、スキルからのブランチとわかるようにブランチ名にプレフィックスを付け、過去のブランチチェックアウトの残骸が新しいPRに混入しないようにします。/deploy-local-preview:ローカル開発サーバーを起動してプレビューするには数行のターミナル操作が必要なため、それをユーザーの代わりに行うスキルを作成しました。対象のサイトに移動し、開発サーバーを起動して、ローカルプレビューをデプロイします。
コンテンツ更新向けスキル
各ページタイプごとに、Frontmatterファイルの作成、フィールドごとのユーザーへの入力促し、画像のアップロード(画像サイズチェックあり)、作業確認のための /deploy-local-preview の呼び出し、GitHub CLIを使ったPull Requestの作成、までを行うスキルを構築しました。これにより必要な情報がすべて揃うよう誘導し、煩雑なCMS UIの操作を減らし、巨大な画像ファイルの使用を防ぎ(250KB以下への圧縮を丁寧に促し、それより大きいファイルは受け付けない)、ページ更新をコードではなくコンテンツだけに集中できるようにしています。
考慮すべき点
AIを使ったコンテンツ更新スキルを構築した経験から、いくつか念頭に置くべきことがあります。
- コンピュートはコストがかかる。 ローカルプレビューのデプロイにはHaikuで十分なのに、Opusを使う必要はありません。タスクに適したモデルが使われるよう、特定のスキルにはデフォルトモデルを設定しています。また、リポジトリのデフォルトモデルはOpus 4.6に設定して使用量を抑えています。
- スキルを使って大きな画像ファイルやパフォーマンスを低下させる一般的な問題を検出する。 巨大な画像がコードベースにアップロードされてビルドやサイトのパフォーマンスを低下させないよう、ページスキルにファイルサイズの上限を設けました。
- Hooksでサイトの重要な部分を保護する。 モデルはコードベース全体にアクセスできるため、変更されたくない重要な部分はAIによる変更を禁止します。例えば、コンテンツセキュリティポリシーは
PreToolUseフックで保護し、CSPへの変更を防いでいます。
「レート制限問題」の解決
内部を改修するついでに、もう一つの悩みの種だったAPIのレート制限問題にも対処しました。
フォームはビルド時にマーケティングオートメーションシステムからフィールドを取得することに依存していました。レート制限に達するとビルドが壊れていました。この問題を解決するために、Vercel Blobを使ったサービスを構築しました。ビルドの冒頭でフォームフィールドを取得し、高速で安定したBlobストアに保存するようにしました。
これにより、ビルドの重要フェーズにおけるマーケティングオートメーションシステムへのAPIコールをほぼゼロに削減し、障害の原因をさらに一つ取り除くことができました。
結果:信頼性という機能
重厚でAPI依存のCMSから、軽量なファイルベースのAstroサイトへの移行は、生産性に大きな変化をもたらしました。
| 指標 | 移行前(Gatsby + CMS) | 移行後(Astro + Claude) |
|---|---|---|
| 平均ビルド時間 | 14分 | 4分未満 |
| Web Vitalsスコア | 89 | 97 |
| ステージングビルドの失敗 | 頻発(API・プラグイン起因) | 95%削減 |
| コンテンツスキーマの制限 | プランによる制限あり | 制限なし |
| 使用感 | 苦痛 | ハイタッチできるレベル |
コンテンツをコードベースに取り込み、非技術者向けにはClaude Codeが橋渡し役を担うことで、サイトを高速化しただけでなく、デプロイパイプライン全体の信頼性を高めることができました。
結局のところ、壊れたビルドを修正する最善の方法は、壊れる原因を最初から取り除くことなのです。
Original Page: How we cut build times by two-thirds by deleting our CMS
IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談は「お問い合わせ」からお気軽にお問い合わせください。





