Blume で作るドキュメントサイト — ポジショニングと拡張の勘所

Blume = 静的サイトジェネレーター

Blume は Astro + Vite ベースの Markdown ファーストな静的サイトジェネレーターです。「Fast, AI-ready, zero-config」を掲げていて、docs/ に Markdown を置くだけで、ナビゲーション・全文検索・テーマ・OG 画像生成・llms.txt(サイトの内容を LLM に読ませるための規定形式のテキスト)までひととおり揃ったドキュメントサイトが立ち上がります。作者は Hayden Bleaselv1.0.0 が出たのが 2026 年 7 月 13 日という、まだできたてのプロジェクトです。

本記事は 2026 年 7 月 25 日・Blume 1.1.4 時点の情報です。v1.0.0 から 12 日で 1.1.4 に達しているとおり更新が速いので、設定名や挙動は最新の公式ドキュメントで確認してください。

私は 「法務案件チェックポイント」 という、Web エンジニア向けに「作る機能・売る商材から疑うべき法令を逆引きする」法務・経理リファレンスサイトを Blume で作っています。しばらく日本語で運用してきて分かった「どういう位置づけのツールで、どこまで手が届くか」をまとめておきます。

この記事は、ドキュメントサイトのツールを選んでいる方に向けて、Blume の立ち位置と拡張のしかたを実運用の目線で紹介するものです。具体的には次のような方を想定しています。

  • Mintlify のような体験を、OSS・セルフホストで実現したい方
  • Starlight など Astro 系のドキュメントツールと比較検討している方
  • ドキュメントを AI/エージェントにも読ませたい方

Astro そのものにはある程度馴染みがある前提で書いており、Astro の基礎は説明しません。

他の静的サイトジェネレーターとの位置づけ

ドキュメントサイト向けの選択肢は今けっこう多いです。ざっくり並べると Blume の輪郭が見えてきます。

ツール 土台 立ち位置
Blume Astro + Vite OSS・zero-config・AI 出力が標準装備
Starlight Astro Astro 公式のドキュメントテーマ。最も近いジャンル
Mintlify SaaS ホスティング込みの商用サービス
Docusaurus React 老舗。i18n・versioning・プラグインが成熟
Rspress Rsbuild (Rust) 高速ビルド。multiVersion などを内蔵

ひとつ断っておくと、この表で実際に運用しているのは Blume だけです。他のツールは公開情報とドキュメントからの整理なので、細かな優劣というより「Blume がどの近辺に立つか」の見取り図として見てください。

Blume の輪郭を一言でいうと 「Mintlify のような体験を、OSS の静的サイトとして、自分のホスティングに置ける形にしたもの」 です。実際、Card / Steps / Tabs / Accordion といった組み込みコンポーネント名や frontmatter の作りは Mintlify にかなり寄せてあります。違うのは、SaaS ではなく blume builddist/ を吐く普通の静的サイトで、GitHub Pages でも Cloudflare Pages でもどこにでも置けることです。

一番近いジャンルは Starlight ですが、差が出るのは AI 向けの出力です。Blume は llms.txt / llms-full.txt / 各ページの .md ミラー / MCP サーバー / 「Open in ChatGPT/Claude」ボタンといった、ドキュメントをエージェントに読ませるための導線を最初から持っています。これらを後付けプラグインではなく標準で持っているのが、2026 年に登場したツールらしいところだと思います。

一方で正直に書いておくと、成熟度では老舗に譲ります。versioning(v1/v2 の切り替え)は UI の入れ物こそあるものの、コンテンツ管理の仕組みはまだ薄いですし、プラグインエコシステムも Docusaurus のような規模ではありません。「枯れた安定」が欲しいなら Docusaurus、「速さと versioning」なら Rspress、という選び方は依然として妥当です。Blume が刺さるのは、新しく作る中〜小規模のドキュメントで、AI 対応と設定の手軽さを重視するケースだと感じています。

なぜ Blume を選んだか

このサイトは、私が書いた技術同人誌『Web エンジニアのための法務確認ガイド』を、逆引きリファレンスに作り直したものです。書籍由来のテキストが主役なので、まず Markdown を置くだけで形になる手軽さが合っていました。

加えて、Astro ベースなので「全ページに免責フッターを必ず出す」といった要件も、スロットに小さなコンポーネントを差すだけで満たせること(後述します)。日本語での運用が設定ひとつで整うこと。この手軽さも効いています。

ただ、いちばん重視したのは AI 向けの出力でした。法務は、エンジニアだけでなく、法務に明るくないディレクターにも確認してほしい領域です。ページをそのまま AI に読ませて質問できる形にしておけば、そういう人にも届きます。同等の AI 機能は商用の Mintlify にもありますが、個人プロジェクトである以上、SaaS の費用がかからない OSS であることも効きました。

逆に versioning のような重量級の機能は要らなかったので、そこが発展途上でも選定の妨げにはなりませんでした。

最大の差別化要因:AI 向けの出力が標準で付いてくる

位置づけの節で「差が出るのは AI 向けの出力」と書きました。ここが一番の売りなので、先に中身を見ておきます。各ページ末尾のアクションメニューと、ビルド時に生成される成果物として、こういうものが最初から出ます。

  • /<route>.md — 各ページの素の Markdown 版(コンポーネントは plain Markdown に変換されます)
  • llms.txt / llms-full.txt — 前者はサイト全体の目次、後者は全ページ本文を 1 ファイルに結合したもの
  • MCP サーバー — MCP(Model Context Protocol)は AI クライアントが外部のデータやツールに接続するための規格です。Blume はそのサーバーを自身でホストし、ページのアクションメニューから接続導線を出します
  • 「Open in ChatGPT / Claude / v0 / Cursor …」 — そのページの内容を各 AI に渡すリンク
  • Copy page / Export to PDF・EPUB — クリップボードコピーとファイル書き出し
  • Ask AI — ドキュメントに対する AI 検索・質問応答

このうち MCP サーバーと Ask AI の 2 つだけは動的エンドポイントを必要とします。後述の output: "server" でのデプロイが前提なので、GitHub Pages のような静的ホスティングでは使えません。

正直に断っておくと、その 2 つは静的ホスティングで運用している本サイトでは有効化しておらず、実地では試せていません。存在と仕組みをドキュメントベースで挙げるにとどめます。残りの静的成果物(.md ミラー・llms.txt / llms-full.txt・Open in chat・PDF/EPUB)は、実際に出力を確認したものです。

「人間向けのリッチな表示」と「エージェント向けの素朴な Markdown」を 1 つのソースから両方出す、という設計思想が通っています。ドキュメントを AI に読ませる前提が当たり前になった時代に作られたツールなんだな、と使っていて感じる部分です。

始め方

とにかく立ち上げるまでが速いです。blume init で雛形を作って、あとは Markdown を書くだけです。

npx blume init      # プロジェクトの雛形を生成
npm install         # 依存をインストール
npm run dev         # 開発サーバー(ホットリロード付き)
npm run build       # dist/ へ静的ビルド

blume init は対話式で、用途に合わせたスターターテンプレート(docs / api / sdk / changelog)を選べます。生成された docs/.md / .mdx を置けば、それがそのままページになります。npm run dev はホットリロード付きなので、書きながら結果を確認できます。

CLI には診断系のコマンドも付いています。blume doctor が設定とコンテンツの健康診断、1.1 系で加わった blume audit が、ビルド済みサイトに対する SEO 中心の監査です。audit は 87 項目のチェックを実行し、しかもオフラインで完結します。サイト監査を SaaS に投げなくても、手元や CI でそのまま回せるのは気楽です。

必要要件は Node.js 22.12 以上です。「まず触ってみる」までの摩擦がほとんど無いのは、zero-config を掲げるだけのことはあります。

設定ファイル一枚でできること

Blume の気持ちよさは、blume.config.ts 一枚でサイトの挙動がほぼ決まるところにあります。手元で運用している設定を例に、何が生えるかを見てみます。

import { defineConfig } from "blume";

export default defineConfig({
  title: "サイト名",
  description: "デフォルト説明文",
  content: { root: "docs" },        // docs/ のファイルパス = URL

  i18n: {                            // UI 文言・日付が言語パックに従う
    defaultLocale: "ja",
    locales: [{ code: "ja", label: "日本語" }],
  },
  dateFormat: { year: "numeric", month: "2-digit", day: "2-digit" },  // → 2026/07/25

  navigation: {
    sidebar: { display: "group" },  // 折りたためるグループ表示
    tabs: [                         // ヘッダーのタブ
      { label: "ドキュメント", path: "/" },
      { label: "更新履歴", path: "/changelog" },
    ],
  },

  seo: {
    x: { handle: "@your_handle" },
    og: {
      enabled: true,
      fonts: [{ name: "Noto Sans JP", weight: [400, 600] }],  // OG 画像の日本語対応
    },
  },

  deployment: {
    site: "https://example.github.io",
    base: "/your-repo",             // サブパス配信
  },

  lastModified: true,               // git 履歴由来の「最終更新」を表示
  feedback: false,                  // 「役に立ちましたか?」を無効化
});

トップレベルで指定できるキーは他にもたくさんあります。よく使いそうなものだけ挙げると、こんなところです。

  • search — 検索プロバイダー
  • export — PDF / EPUB 出力
  • openapi — API リファレンス
  • redirects — URL のリダイレクト
  • markdown — remark / rehype プラグインの追加

このほか logobannertocfrontmatter(独自 frontmatter キーの許可)などもあります。ほとんどの「よくやりたいこと」に専用の口が用意されているので、Vite や Astro の設定に降りていく前に、まず config で片が付くことが多いです。

実運用で効いた設定

このうち、日本語サイトで特に効いたものを挙げておきます。

  • seo.og.fonts — OG カードは自動生成されますが、既定フォントは Latin しかカバーしません。日本語タイトルが豆腐(□□□)になるので、ここでフォント名を指定するとビルド時に Google Fonts から取得して解決してくれます。CJK サイトでは実質必須です。なおこの設定は 1.1.0 で追加されたもので、それ以前は日本語の OG 画像を出す手段がありませんでした(この経緯はまとめで触れます)。
  • i18n(単一ロケールでも) — ロケールを 1 つだけ設定すると、URL 構造は変えずに UI 文言(検索・最終更新・変更履歴)と日付表示だけが日本語圏の形式になります。翻訳サイトを作らなくても恩恵があります。
  • dateFormat — 日付の見た目を Intl.DateTimeFormat のオプションで指定できます。{ dateStyle: "long" } の既定を、上のように数値形式へ差し替えられます。
  • lastModified — git のコミット履歴から各ページの更新日を出します(CI でのクローン設定に注意が要りますが、これは後述のデプロイ節で扱います)。

拡張の勘所 1:theme.css でデザインを詰める

見た目の調整は二層になっています。軽い指定は config の theme、細かい上書きは theme.css という住み分けです。

config.theme で指定できるのは、アクセントカラー・角丸スケール・フォント・初期カラーモード・背景など、いわば「大枠のトークン」です。

theme: {
  accent: "violet",              // または { light, dark } や任意の CSS カラー
  radius: "md",                  // 角丸スケール
  mode: "system",                // system / light / dark
  fonts: { body: "inter", display: "inter-tight" },
},

そこから先の細かい調整は、プロジェクトのルートに theme.css を置きます。これが Blume のカスケードの最終層(base defaults → config のトークン → theme.css)で、CSS 変数を直接上書きできます。ファイル名は規約で決まっていて、ルート直下の theme.css が自動で読まれます。

たとえば手元では、本文の文字色が既定だと白背景で少し薄く感じたので、その 1 トークンだけ濃くしています。

/* theme.css — デザイントークンの上書き(カスケード最終層) */
:root {
  /* 本文・リスト・カード説明文などの文字色。既定 0.54 → 濃く */
  --blume-muted-foreground: oklch(0.3 0 0);
}
:root[data-theme="dark"] {
  /* ダークは背景が黒なので向きが逆(数字を上げるほど際立つ) */
  --blume-muted-foreground: oklch(0.76 0 0);
}

ポイントは、テーマ全体を作り直さなくても、気になるトークンを 1 つずつ狙い撃ちできることです。ライト/ダークはセレクタの詳細度(:root:root[data-theme="dark"])で出し分けます。色は oklch(明度・彩度・色相で色を表す新しい CSS の記法)で持っているので、明度の値だけ動かす調整がやりやすいです。

拡張の勘所 2:components.ts でパーツを差し替え・注入する

Blume のレイアウトには、自作コンポーネントを受け付ける穴が名前付きであらかじめ開いています。これがスロットです。components.ts でスロット名に自分の .astro ファイルを割り当てると、その位置が置き換わる、あるいはその位置に差し込まれます。スロットは 2 種類あります。

  • 差し替え型(組み込みを置き換える):Header / Sidebar / MobileNav / Breadcrumbs / TableOfContents / Pagination / Feedback
  • 注入型(既定は空で、自分の要素を差し込む):Footer(サイト全体の末尾)/ PageHeader(本文の直前・タイトル直上)/ PageFooter(本文の直後)

実例:フッターとシェアメニューを注入する

import { defineComponents } from "blume";

export default defineComponents({
  layout: {
    Footer: "./components/SiteFooter.astro",       // 全ページ共通のフッター
    PageHeader: "./components/ShareMenuTop.astro",  // タイトル直上に何か置く
    PageFooter: "./components/ShareMenu.astro",      // 本文の後に何か置く
  },
});

私のサイトでは 2 つ使っています。ひとつは 全ページ共通のフッター(法律を扱うサイトなので、免責事項を全ページに必ず出す要件があります)。もうひとつは シェアメニューを、タイトル直上と本文末尾の 2 か所に置いています。

差し込む .astro には props として pagetitle など)・routeheadings が渡ってきます。たとえば PageFooter に入れているシェアメニューは、この props から共有 URL を組み立てています(要点だけ抜き出すと、こんな骨格です)。

---
// PageFooter / PageHeader スロットに注入するシェアメニュー(抜粋)
interface Props {
  route: string;
  page: { title?: string };
  placement?: "top" | "bottom";
}
const { route, page, placement = "bottom" } = Astro.props;

// オーバーライドした .astro では MDX と違って base が自動で付かないので、
// 共有 URL は site(オリジン)+ base + route を自分で組み立てる
const base = import.meta.env.BASE_URL.replace(/\/$/, "");
const url = Astro.site ? new URL(`${base}${route}`, Astro.site).href : "";
const title = page?.title ?? "";
const xHref = `https://x.com/intent/post?text=${encodeURIComponent(title)}&url=${encodeURIComponent(url)}`;
---

<div class:list={["share-menu", `share-menu--${placement}`]}>
  <a href={xHref} target="_blank" rel="noopener noreferrer">X でシェア</a>
  <!-- リンクコピー・はてブなども同様に -->
</div>

テーマに追従させるための --blume-background / --blume-border / --blume-content-width といった CSS 変数も、この .astro<style> の中で普通に使えます。

もうひとつのクセが、スロットからはカスタム props を渡せないことです。上のメニューを本文末尾(PageFooter)だけでなくタイトル直上(PageHeader)にも placement="top" で置きたい——と思っても、スロットに props を直接渡す口がありません。そこで薄いラッパーを一枚かませます。

---
// ShareMenuTop.astro — PageHeader スロット用の薄いラッパー。
// placement="top" をここで固定して本体に流すだけ。
import ShareMenu from "./ShareMenu.astro";
interface Props {
  route: string;
  page: { title?: string };
}
---

<ShareMenu route={Astro.props.route} page={Astro.props.page} placement="top" />

これを PageHeader: "./components/ShareMenuTop.astro" に割り当てれば、同じコンポーネントを配置違いで 2 か所に置けます。実装は本体 1 つとラッパー 1 枚だけ。このサイトの独自 UI は、免責フッターとこのシェアメニューでほぼ全部です。

MDX の組み込みコンポーネント

MDX 側の拡張も軽いです。Card / CardGroup / Steps / Tabs / Accordion など 30 以上の組み込みコンポーネントが import なしでそのまま使えるので、記事を書くときにボイラープレートがほぼ発生しません。

デプロイ:普通の静的サイトとして置ける

Blume は blume builddist/ を吐くだけなので、静的ホスティングならどこにでも置けます — GitHub Pages / Cloudflare Pages / Netlify / Vercel / S3 など。押さえるのはビルドコマンド blume build と出力ディレクトリ dist の 2 点だけ。これさえ合っていれば、どのサービスでも動きます。

本サイトは GitHub Pages に置いています。GitHub Actions の要点はこれだけです。

- uses: actions/checkout@v6
  with:
    fetch-depth: 0          # lastModified が git 履歴から日付を取るため全履歴が要る
- uses: actions/setup-node@v7
  with:
    node-version-file: "package.json"   # Node 22.12+
- run: npm ci
- run: npx blume build      # → dist/
- uses: actions/upload-pages-artifact@v3
  with:
    path: dist
- uses: actions/deploy-pages@v5

実運用で踏みやすい注意点をいくつか挙げます。

  • サブパス配信には deployment.base が要ります。 GitHub Pages のプロジェクトサイトは https://user.github.io/repo/ のように配信されるので、base: "/repo" を設定しないと内部リンクや assets が壊れます。逆に Cloudflare Pages などのルート配信では不要です。
  • deployment.site には絶対 URL(オリジン)を設定します。 OG 画像・sitemap・canonical URL・RSS は絶対 URL を必要とするので、これが無いとそれらが出ません。base と重複させると URL が二重連結される(/repo/repo/...)ので、site はオリジンだけにします。
  • lastModified を使うなら CI で fetch-depth: 0 を。 各ページの更新日を git のコミット履歴から取る仕組みなので、既定の浅いクローン(depth=1)だと全ページがデプロイ日になってしまいます(上の YAML の 1 行目がこれです)。
  • 動的機能を使うときだけサーバー出力に切り替えます。 前述の MCP サーバーや Ask AI のような動的機能を有効にする場合のみ deployment: { output: "server", adapter: "vercel" } のようにアダプターを指定します。使わなければ既定の静的出力のままで構いません。

裏を返すと、これらの罠はどれも「一度踏めば設定一行で解決」する類いで、踏んだあとは意識しなくてよくなります。SaaS のような運用のロックインが無い代わりに、この程度の配信設定は自分で持つ、というバランスです。

まとめ

Blume が向いているのは、これから新しく作る中〜小規模のドキュメントサイトで、設定の手軽さと AI 対応を重視するケースです。config 一枚でほとんどが決まり、足りない見た目は theme.css で 1 トークンずつ、足りないパーツは components.ts のスロットで差し替え・注入できます。この「config で 8 割、CSS 変数とスロットで残り 2 割」の刻み方が、ちょうどよく手に馴染みます。

まだ若いプロジェクトなので versioning のような成熟機能は発展途上ですが、その分だけ動きが速いです。日本語で運用していると、英語圏だけで使っていたら踏まないような小さな穴に当たります。当たったものを issue や PR にしていったところ、出した 6 本はどれも数日内に——早いものはその日のうちに、設計判断のコメントつきで——取り込まれました。

いちばん象徴的だったのが、前述の seo.og.fonts です。OG 画像の日本語が豆腐になる件を、ローカルにフォントを置いて読ませる回避策つきで issue に出したところ、Blume が内部で使っている画像生成ライブラリのメンテナまでスレッドに乗ってきました。結果、実装は私が提案した「ローカルフォントのパス指定」ではなく、フォント名を書くだけでビルド時に Google Fonts から取得するという、もっと綺麗な形で 1.1.0 に入りました。個別の回避策ではなく設定サーフェスとして生えたので、他の非 Latin 圏のユーザーもそのまま恩恵を受けられます。

同じことが dateFormat でも起きています。日付の書式を設定で変えられるようにしてほしい、と出した要望が、そのままメンテナの手で実装されました。上の「実運用で効いた設定」に挙げた 4 つのうち 2 つは、そうやって後から生えたものです。

この反応の速さと丁寧さは、まだ若いツールを本番で使ううえで安心できる点だと感じています。

速さは機能の側にも出ています。執筆時点で準備中の 1.2 には、evals.yaml に書いた質問に AI エージェント(既定は Claude Code)がドキュメントだけを使って答えられるかを検証する blume eval が入る予定です。ドキュメントを AI に読ませる前提が、出力する段階から、その出力がちゃんと使えるかをテストする段階まで来ている、ということだと思います。

Astro に馴染みがあって、Mintlify 的な体験を OSS で欲しい人には、いま試す価値が十分にあると思います。


本記事で例に挙げたサイト:

issue / PR のやりとりの詳細は別記事に書きました:

Blume: