このサイト(kai.ryopc.org)は Eleventy + Tailwind CSS v4 + microCMS + Cloudflare Pages の構成で作っています。構築の流れと、実際にハマったポイントをまとめます。同じ構成でブログを作りたい人の参考になれば幸いです。
全体像
採用した技術スタックは次の通りです。
- 静的サイトジェネレーター: Eleventy 3.x(Nunjucks テンプレート)
- CSS: Tailwind CSS v4
- CMS: microCMS(ヘッドレス CMS、ブログ記事の管理)
- ホスティング: Cloudflare Pages(GitHub 連携で自動デプロイ)
記事は microCMS で管理し、ビルド時に API で取得して静的な HTML として生成します。ブログ記事の追加・修正は microCMS の管理画面だけで完結し、再ビルドで反映される仕組みです。
microCMS の記事をビルド時に取得する
Eleventy の設定ファイル(.eleventy.js)でグローバルデータとして記事一覧を取得します。ポイントは、環境変数が無い場合(ローカルでの開発時など)はスキップして空配列を返す点です。API キーなしでもビルドが失敗しないようにしています。
eleventyConfig.addGlobalData("blogs", async () => {
const apiDomain = process.env.MICROCMS_DOMAIN;
const apiKey = process.env.MICROCMS_API_KEY;
if (!apiDomain || !apiKey) {
console.log("⚠️ microCMS の環境変数が見つからないため、記事取得をスキップします。");
return [];
}
const res = await fetch(`https://${apiDomain}.microcms.io/api/v1/blogs?orders=-publishedAt`, {
headers: { "X-MICROCMS-API-KEY": apiKey },
});
if (!res.ok) throw new Error(`microCMS API error: ${res.status}`);
const data = await res.json();
return data.contents;
});環境変数は MICROCMS_DOMAIN(サービス ID)と MICROCMS_API_KEY(API キー)です。Cloudflare Pages の環境変数として設定します。API キーは secret_text で設定するとログに値が出ないので安心です。
一覧ページと記事ページ
一覧ページ(/blog/)は取得した記事をカードのグリッドで表示します。記事ページ(/blog/articles/記事ID/)は Eleventy の pagination を使って記事ごとに静的な HTML を生成します。
pagination:
data: blogs
size: 1
alias: post
permalink: "blog/articles/{{ post.id }}/index.html"タイトルや meta description も記事データから生成できるよう、front matter の eleventyComputed で post 変数を参照します。これで記事ごとに固有の title タグと description が入ります。
ハマりどころ1: Tailwind CSS v4 の preflight が記事本文のスタイルを壊す
microCMS のリッチエディタで書いた本文(見出し・箇条書き・引用・コードなど)に独自のスタイルを当てようとしたところ、箇条書きの・(bullet)が表示されない問題が発生しました。
原因は Tailwind CSS v4 の preflight です。v4 では ol, ul, menu に list-style: none が設定されており、カスタム CSS の .blog-body ul { list-style-type: disc; } がこれに負けていました。v4 は @layer base を使ったカスケードレイヤー構成のため、素朴な上書きでは勝てないのです。
対策として、記事本文用のスタイルには !important を付与しています。Tailwind の preflight やユーティリティと競合する可能性があるセレクタ(見出し・箇条書き・引用・コード・表など)には、優先度を明示的に上げるのが確実でした。
ハマりどころ2: 削除した記事の HTML が出力先に残る
Eleventy はビルド時に出力先ディレクトリ(_site)を自動でクリアしません。microCMS で記事を削除しても、以前ビルドした記事ページの HTML が残り続けてしまいます。記事の削除がサイトに反映されない原因になります。
対策として、ビルド開始前に _site を削除するフックを入れました。
eleventyConfig.on("eleventy.before", () => {
rmSync("_site", { recursive: true, force: true });
});これで常にクリーンな状態からビルドされるので、削除された記事のゴミが残りません。
ハマりどころ3: microCMS の API キー権限(MCP 連携時)
microCMS には MCP サーバー(microcms-mcp-server)があり、エージェントから記事の作成・更新ができます。ところが、読み取り専用の API キーを使うと記事の作成(POST)が 400 POST is forbidden. で失敗します。
対処は microCMS の管理画面(サービス設定 → APIキー)で、対象キーの権限を「読み取り/書き込み」に変更することです。API キーの権限は作成後に変更できるので、書き込みが必要なクライアントには書き込み権限を付与しましょう。
ハマりどころ4: カスタムドメインで CSS が反映されない
Cloudflare Pages のデフォルトドメイン(*.pages.dev)では反映されているのに、カスタムドメインでは古い CSS のまま、という現象に遭遇しました。原因はブラウザや CDN のキャッシュでした。
CSS を変更した直後に確認するときは、シークレットウィンドウやハードリロード(Cmd+Shift+R)で確認すると、キャッシュの影響を切り分けられます。
まとめ
今回の構成は、静的サイトにヘッドレス CMS を組み合わせる定番パターンですが、Tailwind v4 の preflight との戦いや、ビルドのクリーン化など、細かな落とし穴がありました。この記事が同じ構成で作る人の助けになれば嬉しいです。