Web を作る道具を、二層に分ける。
- 中身(コンテンツ): Markdown と Mermaid で書く
- 外枠(フレーム): HTML と CSS と最小限の JavaScript
両者を Python が繋ぐ。これだけで、ビルドが消え、依存が消え、デプロイが軽くなる。そして ── ここが大きい ── 中身が Web 以外の用途にも流用できる。
React の疲れ
過去 10 年、Web 開発は「フレームワークの軍拡」だった。
jQuery、Backbone、Angular、React、Vue、Svelte。ビルドツールは Grunt、Gulp、Webpack、Rollup、Vite、Turbopack。CSS は Sass、Less、PostCSS、Tailwind、CSS-in-JS。サーバーサイドレンダリングは Next.js、Nuxt、Remix、SvelteKit、Astro。
これらは何かの問題を解いてきた。しかし、解いた問題と新しく作った問題を比べると、割に合わないことが増えてきた。
- ビルド設定の習得に数週間かかる
- 依存パッケージが 1000 個以上になる
- セキュリティアップデートが毎週来る
- 一年後にビルドが通らなくなる
- 簡単な Web サイトを作るのに 100 MB のフォルダが要る
これは技術ではなく、自家製の複雑さだ。
WordPress の罠
「自分は React なんか使っていない、WordPress だ」── 多くの人が、現在こう思っているはずだ。
それは正しい。世界の Web サイトの 約 43% が WordPress で動いている。日本でも企業の公式サイト、個人ブログ、ニュースメディア、自治体の Web ── あらゆる場所に WordPress がある。
しかし、WordPress には WordPress の罠がある。React の罠と質は違うが、深刻さは同じか、それ以上だ。
問題 1: コンテンツが MySQL に閉じ込められる
WordPress の記事は、テキストファイルではなく、MySQL の中の HTML 混じりのレコードとして保存される。同じ記事を PDF にしたい、別のサイトに移したい、AI に渡して分析したい ── 全部、エクスポート作業から始まる。
しかも、エクスポート形式は .xml(WordPress 独自の WXR)で、HTML タグや独自ショートコード([gallery] など)が混ざっている。コンテンツが、WordPress に閉じ込められる。これは第4章で見る「Excel に閉じ込められたデータ」と同じ構造だ。
問題 2: プラグインがセキュリティ地雷原
WordPress の機能拡張は、世界中の有志が作ったプラグインに頼る。一つのサイトに 20〜30 のプラグインが入っているのは普通だ。それぞれが定期的に脆弱性を出す。サイト全体が攻撃面の集合体になる。
世界の Web の 43% が WordPress で動くということは、攻撃者にとって 43% の標的が同じ装置だということだ。Mythos 級の AI が来る時代に、これは致命的な構造になる(構造分析シリーズ第5章「Mythos が来た」参照)。
問題 3: アップデートが壊す
WordPress 本体、テーマ、プラグイン ── これらが互いに依存している。一つを更新すると、別のものが動かなくなる。「アップデートを当てたらサイトが落ちた」は WordPress 運用の日常だ。
問題 4: PHP は AI の得意分野ではない
WordPress のテーマやプラグインは PHP で書かれている。Claude は PHP も書けるが、Python よりは出力品質が安定しない。AI ネイティブな仕事の道具立てとして、PHP は最適ではない。
WordPress から抜ける
WordPress を使っているなら、抜け道は明確だ。第6章で見た 並行稼働 と同じパターンで抜ける。
- 既存の WordPress を残したまま、コンテンツを Markdown にエクスポート する(プラグインや CLI ツールで自動化、Claude が変換コードを書ける)
- 新サイトを Markdown + 最小 HTML/CSS + Python で構築する
- 同じ URL 構造を保つ(SEO 評価を維持)
- ステージング環境で動作を確認、検索エンジンへのインデックス申請を準備
- DNS を切り替える日を決める
- 切り替え後、WordPress を読み取り専用にして 1 ヶ月運用
- 問題なければ WordPress を停止、ホスティング契約を解除
費用面の効果も大きい。WordPress のマネージドホスティング(WP Engine、Kinsta など)は月額数千〜数万円。静的 HTML を Cloudflare Pages や GitHub Pages に置けば、月額ゼロ円になる。年間数万〜数十万円が消える。
WordPress も並行稼働で抜ける。Markdown へエクスポートし、外枠だけ HTML/CSS で書き、Python で生成、静的配信する。これで WordPress を殺せる。
中身は Markdown + Mermaid。外枠は HTML+CSS+JS
Web サイトの本質は「中身」と「外枠」に分けられる。
| 種類 | 何を書くか | 道具 |
|---|---|---|
| 中身 | 文章、表、引用、コード、図 | Markdown + Mermaid |
| 外枠 | ヘッダー、ナビ、フッター、レイアウト、配色 | HTML + CSS + 最小限の JavaScript |
| 接続 | 中身を外枠に流し込んで HTML を生成 | Python |
これを混ぜて書くのが、これまでの Web 制作の罠だ。React のコンポーネントには、文章と書式とロジックが全部混ざっている。WordPress の記事には、HTML タグと文章が混ざっている。書き換えが地獄になる。
AI ネイティブな分け方は、中身と外枠を完全に分離する。中身は Markdown と Mermaid だけ。HTML タグは一切書かない。外枠は HTML と CSS で書くが、各記事の中身には触らない。Python が機械的に繋ぐ。
(Markdown)"] MMD["図 *.mmd
(Mermaid)"] end subgraph Frame["外枠"] HTML["template.html"] CSS["style.css"] JS["main.js (最小)"] end Py(("Python
ビルド")) MD --> Py MMD --> Py HTML --> Py CSS --> Py JS --> Py Py --> Site["静的 HTML サイト"] MD -.->|そのまま流用| PDF["PDF / 印刷"] MD -.->|そのまま流用| AI[("AI 分析")] MD -.->|そのまま流用| Book["電子書籍"] classDef content fill:#e8f5e9,stroke:#7a9a6d,color:#3a4d34 classDef frame fill:#fef3e7,stroke:#c89559,color:#5a3f1a class MD,MMD content class HTML,CSS,JS frame
なぜ中身を Markdown + Mermaid で持つか
中身を Markdown と Mermaid で書く最大の理由は、データが Web 以外の用途でも使えるからだ。
同じ Markdown ファイルから、
- Web ページが作れる(Python が HTML 化)
- PDF が作れる(
pandocでも Claude でも変換可能) - 印刷用原稿に変換できる
- 電子書籍(EPUB)が作れる
- AI に渡して要約・翻訳・質問できる
- 別の媒体への貼り付けに流用できる
- Git で差分レビュー・履歴管理ができる
- 他の人と共同編集できる
コンテンツが Web に閉じ込められない。WordPress や Wix で書いたコンテンツは、サービスが終われば消える。Notion で書いたコンテンツは、Notion の形式に閉じ込められる。Markdown は、どこにも閉じ込められない。
これは、第2章「文書を書く」で見た「中身を Markdown に保つ」原則の Web 版だ。入口・中身・出口を分ける:
- 入口: 各種フォーマット(画像、PDF、音声、Word)から Claude が Markdown 化
- 中身: Markdown と Mermaid で持つ(Git でバージョン管理)
- 出口: Web、PDF、印刷、AI 分析、電子書籍 ── 用途に応じて Python が変換
中身は Markdown に保つ。出口に応じて変換する。これが、データを 10 年後も使える形で残す方法だ。
外枠は最小限で書く
外枠 ── ヘッダー、ナビ、フッター、レイアウト、配色 ── は、HTML と CSS で 直接 書く。最小限で。
- HTML テンプレートは 1〜数ファイル
- CSS は 1 ファイル(数百〜数千行)
- JavaScript は本当に必要な要素(モバイルメニューの開閉など)だけ、数十行
これらは年に数回しか触らない。外枠を凝りすぎない。骨格は骨格として置く。時間は中身に使う。
捨てるもの:
- JavaScript フレームワーク(React、Vue、Angular、Svelte)
- ビルドツール(Webpack、Vite、Turbopack、Parcel)
- TypeScript(JS で十分)
- CSS フレームワーク(Tailwind、Bootstrap)
- パッケージマネージャ(npm、yarn、pnpm)
node_modules(rm -rf node_modulesで消える)
残すもの:
- HTML(構造)── テンプレート 1 ファイル
- CSS(見た目)── 1 ファイル
- JavaScript(動的要素のみ、必要最低限)── 数十行
- Markdown + Mermaid(中身)── 記事ごとに 1 ファイル
生の Web 標準と Markdown だけだ。AI が最も書きやすい組み合わせ。HTML / CSS / JS は変換層がなく、Markdown は AI のネイティブ表記。両方とも Claude が出した出力をそのまま使える。
npm を捨てるもう一つの理由 ── サプライチェーンの脆弱性
「ビルドが遅い」「依存が重い」だけが npm を捨てる理由ではない。 もっと深刻なのは、npm の構造そのものが脆弱だということ である。
npm レジストリには、サプライチェーン攻撃が繰り返し発生している: タイポスクワッティング(似た名前のパッケージで誤インストールを誘う)、 プロトタイプ汚染(依存パッケージ経由でのコード注入)、依存パッケージ の乗っ取り(メンテナーアカウント侵害)、ポストインストールスクリプト での秘密情報の流出。検証可能な代表事例だけでも、
- 2018 年:
event-stream事件(暗号通貨ウォレット狙撃) - 2021 年:
ua-parser-js事件(マイニング・情報窃取マルウェア注入) - 2022 年:
colors、faker事件(意図的な破壊コミット) - 2024 年:
xz-utilsバックドア(npm ではないが、長期にわたる メンテナー乗っ取りの典型例)
など、ほぼ毎年 大規模な事件が報告されている。大手企業が公式 配布する npm パッケージが、サプライチェーン経由で攻撃の踏み台に なった事例も繰り返し起きている(個別の事件は本シリーズの 第11章 AIで物語を検証する で扱う検証手法で、各自で一次情報に当たって確認してほしい)。
なぜ npm はこの構造から逃れられないか
問題は、npm のエコシステム設計そのもの にある。
- 一つのプロジェクトが 数百〜数千 のパッケージを推移的に依存する
- それらのパッケージは、世界中の個人メンテナー が管理している
- アップデートは自動でフェッチされる(
npm installで latest が来る) - パッケージマネージャーは依存先のコードを 検査せずに実行 する
- ビルドステップ、postinstall フックなどで任意のコードが走る
このうち一つでも乗っ取られれば、取り込んだプロジェクト全体が侵害 される。1 個のパッケージが、推移的に 1,000 個のリポジトリに影響する という構造は、npm を使う限り避けられない。
npm はモジュール再利用の理想として設計された。 しかし「他人のコードを大量に取り込む」という前提そのものが、 セキュリティ上の脆弱性を構造化している。
Python・HTML/CSS の桁違いの単純さ
これに対して、本書のスタックは依存が 桁違いに少ない。
- Markdown + HTML + CSS + JS:外部依存 0 個(ブラウザ標準のみ)
- Python ビルドスクリプト:
markdown-it-py、Jinja2、Pillowの 3 個
3 個の依存パッケージなら、全てのソースを Claude と一緒に読み通せる 規模である。怪しい挙動があれば気付ける。1,000 個の依存ツリーは、 人間にもチェックできない。
そして Python パッケージは PyPI の重要パッケージほど検査が厳しく、 postinstall で任意コードが走る npm のような構造はない。侵害される 表面積が、桁違いに小さい。
依存ゼロは、AI 時代の最大の防御である
もう一つ、AI 時代に重要な点がある。
Claude Code は、エディタの裏でファイルを読み、コマンドを実行する。
もし開発機の node_modules のどこかに悪意のあるパッケージが潜んで
いれば、AI 経由でその実行が引き起こされる 可能性すらある。
依存を 1,000 個抱えるプロジェクトに Claude を入れることは、 信頼できない 1,000 人の他人を、自分の作業空間に招き入れること と同じだ。
依存ゼロのスタックなら、この心配がない。HTML、CSS、Markdown は プレーンテキストである。実行されるコードは、自分と Claude が書いた ものだけ。
「軽い」「速い」だけでなく、「侵害される入口がない」── これが AI 時代に依存を切り捨てるもう一つの理由である。
Python が両者を繋ぐ
Markdown を HTML に、Mermaid 図を SVG または画像に、外枠テンプレートに流し込む ── これは Python スクリプトの仕事だ。
articles/foo/ja.md ──→ Python ──→ html/foo/index.html
↑
tools/templates/article.html (外枠)
このスクリプトを書く必要は無い。Claude に頼んで書いてもらう。markdown-it-py で Markdown を HTML 化、Jinja2 でテンプレートに流し込む。両方合わせて 100〜200 行で書ける。
依存は 3〜4 つだけ:
markdown-it-py── CommonMark パーサJinja2── HTML テンプレートエンジンPillow── 画像処理(OG 画像生成など、必要なら)- (Mermaid 図はブラウザ側でレンダリングするか、
mermaid-cliで SVG 化)
uv add markdown-it-py jinja2 pillow → git clone && uv sync で完結。
node_modules は無い、requirements.txt も要らない。
このサイト ── aiseed.dev ── のビルドスクリプト(tools/build_article.py)も、ほとんど Claude が書いた。ビルドツールは自分の手元に持つことができる時代だ。フレームワークの規約に従うのではなく、自分の規約で書く。
動的処理は FastAPI 一択
「動的なサイトは作れないのでは?」と思うかもしれない。違う。
動的処理はサーバー側で書く。Python の FastAPI、これ一つでいい。
Flask、Django、Go、Rust、Ruby ── 選択肢は山ほどある。しかし、選択肢を増やせば、組織は分裂する。「FastAPI で書こう」と決めれば、それ以上の議論は終わる。選んだら、選んだことを忘れる。これが AI ネイティブな道具立ての考え方だ。
なぜ FastAPI か:
- Python だから、このシリーズ全体のスタックと一致する
- 型ヒントと Pydantic が自然に使える
- async が標準
- OpenAPI ドキュメントが自動生成される
- Claude が一番書きやすい(オープンソースで学習データが豊富)
- ボイラープレートが少ない
それも、最小限にする
最小限とは、具体的にこういうことだ。
- ORM を使わない。SQLAlchemy は要らない。PostgreSQL ドライバ(asyncpg または psycopg)で SQL を直接叩く
- 層を増やさない。Repository 層、Service 層、Domain 層 ── 要らない。リクエストを受け、SQL を実行し、HTML を返す。それだけ
- 依存を増やさない。FastAPI、PostgreSQL ドライバ、Jinja2(必要なら)── 三つで十分
- 設定ファイルを増やさない。環境変数だけで動く
- マイクロサービスにしない。一つのプロセスで動かす
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
import asyncpg
app = FastAPI()
@app.get("/items", response_class=HTMLResponse)
async def items():
conn = await asyncpg.connect(...)
rows = await conn.fetch("SELECT name, price FROM items")
html = "".join(f"<li>{r['name']}: {r['price']}</li>" for r in rows)
return f"<ul>{html}</ul>"
これだけで、「データベースから商品を取って HTML で返す」サーバーが動く。これ以上の何が要るのかを問い続ける。
Spring Boot の長大なクラス階層、Django の app/middleware/views/serializers、Express + Prisma + GraphQL のスタック ── これらは過去の複雑さの遺産だ。Claude が直接 SQL を書ける時代に、ORM の抽象化は要らない。
クライアント側の JavaScript も最小限。リンク遷移は <a> でいい。フォーム送信は <form> でいい。動的更新が要るなら HTMX(数 KB のライブラリ、フレームワークではない)。WebSocket は本当に必要なときに追加する。最初から SPA を作らない。
これで 9 割は足りる
例えば、社内の在庫管理 Web アプリ:
ブラウザ ─→ FastAPI (Python, 1 ファイル, 200 行) ─→ PostgreSQL
これで動く。フロントエンド、バックエンド、データベース、すべて 1 人で作れる。Claude がコードを書く。ユーザー数百人、レコード数百万件まで普通に動く。
性能のために最初からマイクロサービスを設計する必要はない。実際に詰まったら、その時にスケールアウトを設計する。9 割の業務 Web アプリは、そこまで来ない。
選択肢を絞ることは、自由を捨てることではない。思考を捨てる対象を絞ることだ。技術選択の議論に時間を使わない。FastAPI と SQL と Jinja2 で書く。AI と一緒に。
動的層は、FastAPI 一択、最小限。
具体例:このスタックで何が作れるか
抽象的な「中身 Markdown + 外枠 HTML+CSS + Python が繋ぐ」は、 実例で見るのが速い。
例 1:個人事業主のポートフォリオサイト
- 中身:
portfolio/以下に作品ごとの.mdファイル、画像、 Mermaid 図 - 外枠:
templates/article.html1 ファイル、style.css1 ファイル - Python ビルド:50 行(
markdown-it-py+Jinja2) - 配信:Cloudflare Pages(無料)、独自ドメイン
- 更新:Markdown を書く →
git push→ 自動ビルドして公開 - 規模:30〜100 ページ、ビルド数秒、月額費ゼロ
例 2:中小企業のコーポレートサイト
- 中身:
pages/に「会社概要、サービス、お問い合わせ、ブログ」 の Markdown - 外枠:同じく
templates/+style.css - 問い合わせフォーム:FastAPI を 50 行、SMTP でメール送信 (社内 LAN の miniPC で動かしてもいい、第2章)
- 採用ページの動的部分(求人一覧):SQLite + FastAPI で 30 行
- 配信:静的部分は Cloudflare Pages、動的部分は VPS or miniPC
- 規模:50〜200 ページ、月数千の訪問、月額費 < 千円
例 3:NPO のイベント告知サイト
- 中身:
events/2026-04-foo.mdのようなイベントごとの Markdown - 過去イベントのアーカイブ:
events/に蓄積、年別の目次は Python が自動生成 - イベント詳細の地図:Markdown 中に
<iframe>か、Mermaid の 位置関係図 - 申し込みフォーム:Google Form リンク(動的部分が要らない) または FastAPI で 30 行
- 配信:GitHub Pages か Codeberg Pages(無料)
例 4:学校教師の学級通信サイト(保護者限定)
- 中身:
weekly/2026-04-week-1.mdのような週次 Markdown、 写真、Mermaid で行事カレンダー - 外枠:学校カラーで
style.cssを 1 ファイル - アクセス制限:Basic 認証(
htpasswd)で保護者限定、または Forgejo に private で置いて保護者にアカウント発行 - 配信:学校の miniPC で社内 LAN 公開、または Cloudflare Tunnel で外部アクセス
- 更新:教師が Zed で
.mdを書く →git pushで配信
例 5:研究室の論文・データ公開サイト
- 中身:論文 Markdown(MyST で計算結果埋め込み、第2章)、 データセットのメタデータ
- データ DL リンク:Parquet ファイル(第4章)を直接 DL
- 可視化:D3(第3章)でインタラクティブ図表
- 配信:大学のサーバーか、Codeberg
これらに共通するのは 依存パッケージが 3〜4 個、ビルド数秒、月額 費ほぼゼロ、AI がほとんどのコードを書く。React + Next.js + 各種 SaaS で組むよりも、作るのも保守も桁違いに軽い。このサイト (aiseed.dev)自身がこの構成だ。
デプロイも軽い
静的 HTML のデプロイは、ファイルをコピーするだけだ。
- Cloudflare Pages、GitHub Pages、Netlify、Vercel ── 全部無料か低価格
- 自分のサーバーに置きたければ、
scpで送るだけ - CDN に乗せれば、世界中で高速
CI/CD パイプラインも単純になる。「Markdown が変わったら Python ビルドして、HTML を CDN にアップロードする」── 数行のスクリプトで終わる。
10年後も動く
React のバージョン v15 で書いたコンポーネントは、v18 ではビルドできないことがある。Webpack の設定は 1 年ごとに書き直しを迫られる。
HTML、CSS、JavaScript の基本仕様は、25 年以上後方互換が保たれている。1999 年の HTML ファイルは、今のブラウザでも問題なく動く。生の Web 標準は時間に強い。
Markdown も、20 年前の規格(2004 年初版)からほとんど変わっていない。20 年後も同じファイルが読める。外枠も中身も、時間を超える形式で持つ。
フレームワークは時代に依存する。Web 標準と Markdown は時代を超える。
実例: 数字で見る
React + Next.js + TypeScript + Tailwind で業務 Web 構築: 開発 3 ヶ月、依存パッケージ 約 1,200 個、ビルド時間 3 分、node_modules 500 MB。同じ機能を HTML+CSS+FastAPI+Markdown で構築: 開発 2 週間、依存 4 個、ビルド 5 秒、合計 10 MB。
WordPress マネージドホスティング(WP Engine、Kinsta 等): 月額 5,000〜30,000 円。静的 HTML を Cloudflare Pages: 月額 ゼロ円。年間 6 万〜36 万円の節約。
ページ表示速度: Next.js + Vercel の動的レンダリング 約 800 ms。静的 HTML + CDN 約 50 ms。16 倍速い。
このサイト(aiseed.dev)の規模: 150 ページ以上、合計 30,000 行のコード、24 時間で組み上げた。React・Next.js・TypeScript はゼロ。Markdown と Mermaid と最小 HTML/CSS だけ。
まとめ
Web を作る道具を、二層に分ける。
中身は Markdown と Mermaid。外枠は HTML と CSS と最小限の JavaScript。両者を Python が繋ぐ。
これでビルドが消え、依存が消え、デプロイが軽くなる。そして、中身が Web 以外の用途にも流用できる。同じ Markdown が、PDF にも、印刷にも、AI への入力にも、電子書籍にもなる。
このサイトがその実証だ。30,000 行のコード、150 ページ以上、24 時間で組み上げた。React は使っていない。Markdown と Mermaid と最小 HTML/CSS。それで何の問題もない。
次の章では、アプリを作る話に進む。CLI ツール、Flet アプリ、Flutter アプリ ── 段階的にスケールアップ。
関連記事
- 第3章: 文書を書く ── Markdownという最小の選択
- 第4章: デザインをする ── Mermaid と Claude デザインで作る
- 第7章: 業務システムと付き合う ── 並行稼働で書き換える
- 第2章: 処理を書く ── AIにPythonで書いてもらう
- 構造分析15: Mythos時代のセキュリティ設計
実例
再現可能なソース・コマンド・実測結果を、別ページにまとめてある。