
はじめに — 自分のプロダクトで自分のサイトを診断する
ZERONOVA LAB MCP Server は、AIエージェントがWebサイトの品質検査を実行するためのツールです。MCP Server開発記で書いたとおり、「Workflow as a Tool」パターンで複数の検査を1コマンドに凝縮しています。
開発が一段落して、ふと思いました。「このツールで自分のサイトを診断したらどうなるだろう?」
自分で作ったプロダクトを自分で使う——いわゆるドッグフーディングです。82個の無料ツールを作り、SEO監査の自動化まで実装した MCP Server で、そのホスティング元である zeronova-lab.com を検査する。結果を見て、問題があれば即座に修正する。すべて Claude Code の中で完結できるはずです。
結論から言うと、初回のスコアは64点。5つの高優先度の問題が検出され、そのうち3つを同日中に修正して88点まで引き上げました。
最初の診断 — 64点という現実
run_web_launch_audit を zeronova-lab.com に対して実行しました。このワークフローツールは、セキュリティヘッダー、OGP、alt属性、リンク切れ、ページ速度、見出し構造、canonical、JSON-LD、robots.txt、サイトマップの検査を内部で連鎖実行し、スコア付きレポートを返します。
自作 MCP Server(zeronova-lab-mcp)の公開前チェックツールで zeronova-lab.com を診断。5つの優先度高の改善項目が検出され、うち3つを即日対応
開発日記にはこう記録しましたが、正直なところ64点は予想より低い数字でした。100本以上の記事を書き、SEO対策も丁寧にやってきたつもりだった。しかし自分のツールは容赦なく問題を指摘してきます。
検出された5つの問題は以下の通りです。
- セキュリティヘッダーが未設定(42点/100点) — 基本的なHTTPヘッダーが一切設定されていない
- カラーコントラスト違反(677箇所) — WCAG AA基準を満たさない
text-gray-500がサイト全体に散在 - Google Fonts CDNへの外部リクエスト — レンダリングブロッキングリソースがパフォーマンスを低下させている
- 見出し階層の不整合 — H2を飛ばしてH3を使っている箇所
- メタディスクリプションの長さ — 一部ページで推奨文字数を超過
上位3つは即日修正可能と判断し、着手しました。
セキュリティヘッダーの追加 — 42点から83点へ
最初に手を付けたのはセキュリティヘッダーです。スコアが42点と最も低く、改善インパクトが大きいと判断しました。
Next.js の headers() 設定で全ルートに4つのヘッダーを追加しました。
// next.config.ts(要点のみ)
headers: () => [
{
source: "/(.*)",
headers: [
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
],
},
],
CSP(Content Security Policy)は見送りました。YouTube埋め込み、IdeaSPoolウィジェット、Google Fonts APIなど外部リソースとの互換性が複雑で、誤設定するとサイトが壊れるリスクがあります。PMとして「安全に改善できる範囲で確実に対応する」判断です。
X-Frame-Options: DENY の影響調査
X-Frame-Options: DENY を設定するとき、1つ気になることがありました。サイト内にはYouTube埋め込みiframeや、診断コンテンツジェネレーターの srcDoc iframeがあります。これらが壊れないか。
調査の結果、どちらも問題ありませんでした。YouTube iframeは「外部コンテンツをこのサイトに埋め込む」方向であり、X-Frame-Optionsは「このサイトを他のサイトにフレーミングさせない」方向の制御です。方向が逆なので影響しません。srcDoc iframeはHTTPリクエストが発生しないため、ヘッダーの検証自体が行われません。
この修正だけでセキュリティヘッダーのスコアが42点から83点に改善しました。
カラーコントラスト改善 — 677箇所の一括修正
次に取り組んだのが、サイト全体に散在するカラーコントラスト違反です。
ダーク背景(#0a0a0a)上で使っていた text-gray-500(#6b7280)は、WCAG AAが求める4.5:1のコントラスト比に対して4.04:1しかありませんでした。130ファイル、677箇所。個別に判断するより一括置換が確実です。
Claude Code に text-gray-500 を text-gray-400(#9ca3af、コントラスト比6.58:1)に一括置換を依頼しました。事前に text-gray-500 hover:text-gray-400 のようなhover状態パターンがないことを全ファイル検索で確認し、Journal記事のコード例に含まれる3件は意図的に除外しました。
PM-AI 対話: 一括置換のリスク判断
text-gray-500 を意図的に使っている箇所がないか心配だ。全部変えて大丈夫か確認してほしい。text-gray-500 と hover: や focus: が同じ要素に共存するパターンは0件です。Markdown記事内のコード例が3件ありますが、これらは記事コンテンツなので除外すべきです。一括置換は安全に実行できます。この判断は、後で一部を修正することになります。
next/font 移行 — 外部リクエストをゼロに
3つ目の修正は、Google Fonts CDN から next/font/google への移行です。
もともと layout.tsx に <link> タグ3本(preconnect 2本 + stylesheet 1本)で Google Fonts から Inter と JetBrains Mono を読み込んでいました。これがレンダリングブロッキングリソースとなり、LCP(Largest Contentful Paint)に悪影響を与えていました。
next/font/google はビルド時にフォントファイルをバンドルするため、ランタイムの外部リクエストがゼロになります。CDN依存がなくなることで、パフォーマンスが84点から96点に改善しました。
Canvas APIの予期しない破損
ところが、この移行で思わぬ問題が発生しました。ファビコンジェネレーターのプレビュー機能が動かなくなったのです。
原因は、next/font のフォント登録の仕組みにありました。next/font はフォントをハッシュ付きの名前(たとえば __Inter_abc123)で登録します。Canvas APIの ctx.font に "Inter" と指定しても、そのフォント名はブラウザに登録されていません。
next/font 移行後、Canvas API の
ctx.fontに "Inter" を指定してもフォントが見つからない問題を発見。原因: next/font はフォントをハッシュ付き名前で登録するため
Claude Code に修正を依頼し、getComputedStyle でCSS変数 --font-inter の値を読み取って実際のフォント名を取得する resolveCanvasFont() ヘルパーを実装しました。他のCanvas API使用ツール4つ(ダミー画像、電子書籍作成、ワードクラウド、Webフォントプレビューアー)は Google Fonts API から直接フォントデータを取得する設計だったため、影響はありませんでした。
1回目の修正結果 — 64点から73点へ
3つの修正をデプロイした後、再度 run_web_launch_audit を実行しました。
- セキュリティヘッダー: 42点 → 83点
- パフォーマンス: 84点 → 96点
- 総合スコア: 64点 → 73点
大きな改善ですが、まだ改善の余地があります。残りの見出し階層やメタ情報の問題にも対応し、2回目の修正で総合スコアは88点に到達しました。
一括置換のリグレッション — 共有コンポーネントの罠
88点に到達して安心していたところ、問題が見つかりました。Focus Blog(白背景のページ)のテキストが薄くなっている。
原因はカラーコントラストの一括置換でした。AuthorCard、ShareButtons、TableOfContents——これらの共有コンポーネントは isDark propでダーク/ライト背景を切り替える設計です。
// 一括置換前
className={isDark ? "text-gray-400" : "text-gray-600"}
// 一括置換後(リグレッション)
className={isDark ? "text-gray-400" : "text-gray-400"}
一括置換は「ファイル単位」で除外していましたが、共有コンポーネント内の三項演算子の一方だけを保護する方法はありません。text-gray-500 → text-gray-400 の置換が、ライトモード用の text-gray-600 も巻き込んでしまっていたのです。
3コンポーネントとも
isDark ? "text-gray-400" : "text-gray-400"のように両分岐が同じ値になっていた(=一括置換の副作用)
ダーク背景では問題ない色が、白背景ではコントラスト比2.6:1(WCAG AAの4.5:1を大幅に下回る)になります。さらに、bg-gray-200 上の text-gray-400 はコントラスト比1.5:1で、弱視のユーザーにはほぼ読めない状態でした。
Focus Blog の emerald 問題
同じタイミングで、Focus Blog のブランドカラー text-emerald-600 も白背景上でWCAG AA不足(3.69:1)であることに気づきました。text-emerald-700 に変更することでコントラスト比7.0:1を確保しました。
学んだこと: 2つの背景色基準には2つの補助テキスト色が必要
この経験から重要な原則が見えました。サイト内にダーク背景とライト背景の両方がある場合、補助テキスト色も2つ必要です。
- ダーク背景(
#0a0a0a):text-gray-400(コントラスト比6.58:1) - ライト背景(
#ffffff):text-gray-600(コントラスト比6.18:1)
1色で統一しようとすると、必ずどちらかの背景でコントラスト不足になります。一括置換は「コードパス単位」で影響を考えるべきであり、「ファイル単位」の除外では不十分でした。
ドッグフーディングの循環 — v0.5.0で再診断
2月22日、MCP Server v0.5.0をリリースしました。キャッシュヘッダー、構造化データ、リダイレクト、画像最適化の4つの検査ツールを追加したバージョンです。
リリース直後に、再び自サイトを診断しました。結果は84点。v0.5.0で検査項目が増えた分、88点から下がっています。しかし、検査が厳しくなったことで新たな改善ポイントが見える。
結果を見る→改善する、のループがエディタから一歩も出ずに回る。作って良かったと素直に思えた。
MCP Serverで診断を実行し、結果を読み、Claude Code に修正を依頼する。このサイクルがエディタの中だけで完結します。ブラウザを開いてツールにURLを入力する必要がない。MCP Serverの設計コンセプト——「AIエージェントを顧客として扱う」——が、自分自身のワークフローで実証されました。
PM-AI 対話: 診断と修正の境界
ドッグフーディングを通じて、MCP Serverの設計について新しい視点が生まれました。
学んだこと
ドッグフーディングは2つの品質を同時に上げる: 自分のサイトを自分のツールで診断することで、サイトの問題が見つかると同時に、ツールの実用性も検証できます。診断結果がおかしければツールのバグ、正しければサイトの問題。どちらに転んでも改善につながります。
一括置換は「コードパス単位」で影響を考えるべき: ダーク/ライト両対応の共有コンポーネントがある場合、ファイル単位の除外では三項演算子の片方を保護できません。677箇所の一括置換で3コンポーネントにリグレッションが発生したのは、この原則を見落とした結果です。
MCP Serverとコードエディタの相性は抜群に良い: 診断 → 結果の確認 → コード修正 → 再診断のループがエディタから出ずに回ります。ブラウザベースのツールにはないこの利点は、MCP Serverの本質的な価値です。
検査項目が増えるとスコアは下がるが、それは正しい: v0.5.0で88点から84点に下がったのは後退ではなく、検査の精度が上がった証拠です。スコアの絶対値より、検出された問題を1つずつ潰していくプロセスに意味があります。
段階的に改善する姿勢が大切: 初回64点から73点、73点から88点、そして検査基準の変更で84点。完璧を一度に目指すのではなく、診断と修正のサイクルを回し続ける。SEO監査の段階的自動化で学んだパターンが、サイト品質改善にもそのまま当てはまりました。
Zeronova(ゼロノバ)
Product Manager / AI-Native Builder
Web/IT業界19年以上・20以上のWebサービスを担当したPdM。東証プライム上場企業の子会社代表として事業経営を経験。現在はAIを駆使して企画から実装まで完結させる個人開発を実践中。