メインコンテンツへスキップ
EXBANK
Insights一覧へ
プロダクト2026.05.059分EXBANK 編集部

自社ブログ投稿システムを 1 日で作った話 — AI と組んで 20 記事 + 60 画像を本番化した実装記録

Next.js 16 + MDX + Satori + Claude で、ファイルを置くだけで公開されるブログ基盤を構築。20 記事 + 60 インフォグラフィックを同時公開するまでに踏んだ 7 つの罠と突破方法を、実装目線で残します。

#Next.js#MDX#Satori#AI協業#開発記録#ブログCMS
78% が完読|1,247 views

5 月 5 日、夕方 17 時。1 本のテスト記事を書き上げた直後、私たちはまだ何の 公開インフラも持っていませんでした。

ブログを公開する CMS も、画像生成のパイプラインも、CTA を仕込む構造もない。それを「今日中に 20 記事 + 60 画像を本番公開できる状態にする」と決めました。

15 時間後の翌朝。あなたが今読んでいるこのブログそのものが、その夜の成果です。本記事では、Next.js × MDX × AI 協業で構築した自社ブログシステムの 設計・実装・つまづき を実装記録として残します。

完成したもの — 数字で並べる

抽象的な設計思想を語る前に、まず実物を数字で示します。

項目
公開記事数20 本(5/5 公開 1 + 5/6〜5/24 予約 19)
自動生成インフォグラフィック60 枚(カバー + 本文 2 枚 × 20 記事)
インフラ月額0 円(Vercel 無料枠 + Resend 無料枠)
デプロイ手段vercel --prod 1 行
投稿手段MDX ファイルを置くだけ
平均ページ表示速度(warm キャッシュ)49〜59ms
ローカル dev → 本番デプロイの差dev 11,640ms → 本番 49ms(約 240 倍 高速)

技術スタック:

  • Next.js 16(App Router、Webpack 強制 / Turbopack は日本語パスでパニック)
  • MDX + gray-matter(frontmatter 解析、ファイルシステム読込)
  • Satori + resvg-js(JSX → SVG → PNG のコード生成画像)
  • Resend(送信メール)
  • Vercel(ホスティング + CDN + SSL 自動発行)
  • Claude Code(実装パートナー)

設計思想 — 「ファイルを書く」だけで終わる

ブログを運用するうえで、書く側と表示側の摩擦が一番のコストです。

WordPress なら GUI で書けますが、AI に書かせるには API 連携が必要。Notion CMS なら API は便利ですが、毎回同期するレイテンシがある。Headless CMS(microCMS / Strapi)も同じ問題があります。

結論として、src/content/insights/.mdx ファイルを git に置くだけで公開される方式にしました。AI(Claude Code)に「このファイルを書け」と指示するだけで完結します。

ファイルを置くだけで公開される設計
ファイルを置くだけで公開される設計

💡 KEY TAKEAWAYS
ブログ CMS の選定で迷ったら、まず「誰がコンテンツを書くか」を決めてください。AI 主体ならファイルベース MDX、手動主体なら GUI 中心の Notion / WordPress。当方は AI 主体なので MDX 一択でした。

AI と組める「業務体力」が御社にあるか、3 分でセルフチェックしませんか?
細マッチョ企業診断 / 3 分 8 問
診断する

7 つの落とし穴 — 実装中に転んだ場所

ここからが本題です。15 時間で 20 記事 + 60 画像を本番化するまでに、7 箇所で立ち止まりました。それぞれ、転んだ理由と突破方法を共有します。

落とし穴 1: gray-matter の date は string ではなく Date オブジェクト

予約投稿(公開日まで非表示)を実装したとき、なぜか すべての記事が消える 現象が発生しました。

原因は frontmatter の date 解析。YAML で date: 2026-05-05 と書くと、gray-matter は JavaScript Date オブジェクト として返します。文字列化すると "Tue May 05 2026 09:00:00 GMT+0900" のようになり、"2026-05-05" との単純比較が壊れます。

``js
// "Tue May 05..." > "2026-05-05" → 辞書順で true("T" > "2")
// → 全記事が「未来日付」扱いでフィルタされる
`

突破: 読み込み時に JST に揃えてから ISO YYYY-MM-DD に正規化するヘルパーを 1 つ追加。本番環境のタイムゾーンが UTC である件もここで吸収しました(Vercel は UTC、JST との 9 時間ズレで日付が 1 日ズレるのは別の罠)。

落とし穴 2: Reveal アニメーションで本文が永久に opacity 0

framer-motion の useInView を使ったフェードイン演出で、JS 失敗時や IO 不発火時に文字が完全に消える 問題が発生しました。

特に複合的な事故が起きたのは、本文中間に CTA バナーを差し込む機能を追加した瞬間。

それまで

の中身は子 div 1 つでしたが、CTA 挿入で前半 + バナー + 後半の 3 つの子 div に分割。Animator の document.querySelector(".article-body > div") は最初の 1 つしか取らないため、後半の文字が永久に opacity 0 のまま で表示されませんでした。

突破: 設計を反転しました。デフォルト opacity 1、JS が走った時だけ .ab-pending クラスを付けてフェード演出を有効化。「壊れても文字は読める」を最優先に。

落とし穴 3: 画像 AI でインフォグラフィックは作れない

最初は Codex(画像生成 AI)でインフォグラフィックを作ろうとしました。プロンプトを 60 個書いて、画像 AI に投げる。

結果は壊滅的でした。

私が書いたプロンプトの中身(CSS 仕様・カラーコード・レイアウト指示)が、そのまま画像内のテキストとして配置されたのです。「#ffffff / #c8c8d0」「縦長フローチャート的にステップ 01→02→03→04」という 人間向けの仕様書 を、AI が「画像に書き込む文字」と解釈しました。

根本問題は、画像 AI が「正確なテキスト・数字・レイアウト」が苦手という技術的限界です。マーケ用インフォグラフィックには相性が悪い。

突破: コード生成方式に切り替え。Satori(JSX → SVG)+ resvg-js(SVG → PNG) で 4 種類のテンプレ(cover / flow / grid / comparison)を実装。JSON で「データ + テンプレ種別」を指定すれば、コマンド一発で 60 枚を 30 秒で生成できる構造に。

コード生成インフォグラフィックの 4 テンプレート
コード生成インフォグラフィックの 4 テンプレート

落とし穴 4: Satori が calc() を解釈しない

JSX で書いた width: "calc(33.333% - 12px)"無視される ことに気づいたのは、出力が縦 1 列に並んだ時です。

Satori は CSS の完全実装ではなく、サブセットのみ対応しています。calc() はサポート外。background-clip: textbox-decoration-breakmask-image も非対応です。

突破: JS 側でピクセル計算してから渡す

`ts
const totalW = 1040;
const gap = 16;
const cardW = Math.floor((totalW - gap * 2) / 3); // 3 列幅を実数で
`

事前に Satori の CSS サポート表を確認すべきでした。動作検証フェーズをテンプレ実装より先に置くのが教訓です。

落とし穴 5: ブロックエディタが server component で動かない

WordPress 風の編集 UI を求める声に応えて BlockNote を導入。1 行目で window is not defined で SSR がクラッシュしました。

ブロックエディタ系(BlockNote / TipTap / Lexical)は クライアント専用 です。Next.js 16 では ssr: false を server component から指定できないため、間にクライアントラッパーを挟む 必要があります。

`ts
// editor-loader.tsx (client)
"use client";
import dynamic from "next/dynamic";
export const Editor = dynamic(() => import("./editor"), { ssr: false });

// page.tsx (server) — server から Editor を import
import { Editor } from "./editor-loader";
`

Next.js 15 までと挙動が変わっている部分。AGENTS.md に「Next.js 16 は破壊的変更が入っているので、書く前に docs を読め」と書いておいたのが効きました。

落とし穴 6: markdown のテーブルが描画されない

「読みやすくするため表を入れて」と書いた MDX を本番で確認したら、| col | がそのままテキスト として表示されていました。

私が書いた最小 markdown レンダラに テーブルパーサが実装されていなかった ためです。書く前に renderMdx の対応構文を確認すべきでした。

突破: |---|---| の区切り行を検知して

を生成する 20 行のパーサを追加。同時に 画像
alt
alt
のレンダリング もカバーされていなかったので追加(同じく実装ミス)。

教訓: MDX を採用するなら renderMdx の対応構文表をテストとセットで持つ。書ける構文と書けない構文を、執筆者(AI 含む)が把握できる形にする。

落とし穴 7: DNS の権威ネームサーバー間レプリケーション

XServer から Vercel に DNS を切り替えたとき、ns2 / ns4 / ns5 は新 IP を返すのに ns1 / ns3 は古い IP を返し続ける 現象が起きました。

各 NS が完全同期するまで 15 分 かかりました。Vercel の SSL 自動発行は 全 NS 反映後に開始 するため、ここを早めようがありません。

突破: 待つ。事前に TTL を 300 秒くらいに下げておくと、切替時の不整合期間を短縮できます(教科書通りですが、実際にやってみないと「複数 NS で時差レプリケーションが起きる」とは気づきません)。

改善したい点

書いている時点で「もう少し丁寧に作っておけばよかった」と感じている部分です。次の 1〜2 週間で実装する予定。

1. ISR + Cron でインスタント公開

現状は revalidate = 3600 で 1 時間ごとにキャッシュ更新する設計。0:00 JST 公開予定の記事が表示されるのは最大 1 時間後です。

理想は Vercel Cron + Deploy Hook で 0:00 JST にトリガーして即時再ビルド。

2. renderMdx の自動テスト

落とし穴 6 のような「書いた markdown が描画されない」事故を再発させないため、E2E テストを追加すべきです。Vitest + @playwright/test でテーブル・画像・コード・マーカーすべての描画確認を CI に組み込む計画。

3. 画像生成テンプレートの拡張

現在 4 テンプレ(cover / flow / grid / comparison)+ stats(実装はあるが未活用)。今後追加したいもの:

  • bar chart — 数値比較(CPA -42%、CV +390% など)
  • donut — 構成比可視化
  • timeline — 月次推移
  • mockup — LP のセクション構造図解

4. プレビュー環境

予約投稿された未公開記事を社内向けにプレビューする URL がまだありません。?preview=token のような仕組みを 5/8 までに追加予定。

5. 自動リンク切れチェッカー

CI に組み込んで、PR ごとに記事内リンクの 404 を検出する仕組み。Markdown の text をパースして HEAD` リクエストする 50 行スクリプトで対応可能です。

1 日で組むコツ

最後に、開発時間を 15 時間に圧縮できた理由を 4 つにまとめます。

詳細: 4 つのコツの中身
  1. AI と並列分担: 私(人間)が設計・整合性管理、AI が実装・量産。両者の境界を明確にする。AI に判断を委ねず、人間が判断を委ねない。
  2. データ駆動で量産: 20 記事も 60 画像も、JSON / MDX のデータが先。コードはテンプレ化すれば、残りはデータを流すだけ。
  3. 完成度より構造: 60 画像を細かく磨くより、テンプレを 4 つに絞り込んで全部に同じ温度で適用。微調整は本番反映後に効く順で。
  4. 運用も同じ仕組みに乗せる: AI が将来も使う仕組みを、人間が書きやすい形に揃える(MDX を選んだ理由)。

逆に「やってはいけなかった」と感じたのは、画像 AI に正確なインフォグラフィックを期待したこと(落とし穴 3)と、最小実装の renderMdx に過信したこと(落とし穴 6)。自分が書いた小さい仕組みを、過信しない。これが最大の教訓です。

次のアクション

EXBANK では、こうした AI と組む業務体制の構築支援 も行っています。「ウチも AI で動ける体質か?」と気になった方は、まず 細マッチョ企業診断 で 3 分セルフチェックしてみてください。AI を入れる前提の業務体力(贅肉が少ない、変化対応が速い)があるかが 5 軸で可視化されます。

ブログシステム自体の実装に興味がある方は、お問い合わせフォームでご連絡ください。具体的な構成・設定ファイル・落とし穴の追加情報を、可能な範囲で共有します。

— DIAGNOSIS

この実装も、AI と組める「業務体力」あってこそ。御社の現在地を診断しませんか?

3 分 8 問で、御社の「変化対応力」を 5 軸スコア + 5 タイプで診断します。 登録不要・無料・その場で結果が出ます。

細マッチョ企業診断 を試す

よくあるご質問

Q1.なぜ WordPress を使わなかったのですか?

A.記事を書く側(人間 + AI)と、表示する側(Web)の摩擦をできるだけ減らしたかったためです。MDX ファイルを git に置くだけで公開される構造にすれば、AI に「ファイルを書け」と指示するだけで完結します。WordPress は GUI 編集の柔軟さがありますが、AI 自動化との相性は MDX の方が圧倒的に良いです。

Q2.開発期間は本当に 1 日ですか?

A.コア機能(MDX 読込・予約投稿・インフォグラフィック生成・CTA 統合)の実装は 1 日で動きました。ただし「20 記事のコンテンツ作成」と「60 画像のテンプレ磨き込み」を含めて、実時間ではおよそ 12〜15 時間です。AI(Claude Code)と並列でファイル生成しなければこの速度は出ません。

Q3.画像生成 AI は使わなかったのですか?

A.最初は Codex(画像生成 AI)でカバー画像とインフォグラフィックを作ろうとしました。しかし「正確なテキスト・数字・レイアウト」が必要なインフォグラフィックは画像 AI が苦手な領域でした。最終的には Satori(JSX → SVG → PNG)でコード生成する方式に切り替えました。詳細は本文の落とし穴 3 をご参照ください。

Q4.個人ブログでも使える構成ですか?

A.はい。Next.js + MDX + Vercel で月額 0 円で動きます。ホスティングコストはアクセス急増時のみ発生するため、月数千 PV 規模なら無料枠内です。EXBANK のブログもこの構成です。

Q5.コードはオープンソース化しますか?

A.現時点では予定がありません。ただし、Satori のテンプレ生成と予約投稿の実装パターンは別記事で詳細解説する予定です。

Q6.AI が書いた文章を SEO 的にどう扱っていますか?

A.Google は「AI 利用の有無は順位に影響しない、品質だけ見る」と公式に述べています。当方ブログは AI が下書き → 編集部が事実検証 + 数値追加 + 文体調整というワークフローで、最終的な「品質責任」は人間が持つ運用です。

この施策を御社にも導入しませんか?

無料診断で、御社の状況に合った具体プランをご提案します。

無料診断を受ける