Blume 2 へのアップグレード
1 つのコマンドで Blume 1 のサイトを Blume 2 に移行し、設定の変更ごとにこのガイドを参照してください。アップグレード全体を Claude Code や Codex に任せることもできます。
Blume 2 で変わるのは設定だけで、コンテンツは変わりません。削除された search.boost フロントマターフィールドを設定しているページを除き(フロントマター を参照)、Markdown や MDX のページを編集する必要はありません。以前は名前付きの文字列やキー付きのブロックで指定していた設定は、blume/* サブパスからインポートして呼び出すアダプターになりました。対象は検索プロバイダー、デプロイ先、コンテンツソース、API リファレンス、アナリティクス、Ask AI のバックエンドです。機械可読な設定は ai から新しい agents キーに移動しました。また、components.ts のオーバーライドはビルド前にチェックされるようになりました。ゼロコンフィグのサイトや、これらの設定をどれも使っていないサイトでは、バージョンを上げるだけで済みます。
1 つのコマンドでアップグレードする
プロジェクト(blume.config.ts があるフォルダー)でアップグレードを実行します:
npx blume@latest upgradepnpm dlx blume@latest upgradeyarn dlx blume@latest upgradebunx blume@latest upgradenubx blume@latest upgradeaube dlx blume@latest upgradeこのコマンドは package.json 内の blume を 2 に上げ、プロジェクトで使っているパッケージマネージャーでインストールします。その後、設定と components.ts が Blume 2 に対応しているかをチェックします。まだ必要な変更はすべて、ファイル、行、置き換え内容とともに一覧表示されます。削除された blume build フラグをまだ渡している package.json のスクリプトもここに含まれます。変更が残っている間は、コマンドは 0 以外の終了コードで終了します。設定も blume の依存関係もないフォルダーで実行した場合は、エラーで停止します。blume ではなく npx blume@latest で実行してください。このコマンドは Blume 2 に含まれているため、まだ 1 を使っているプロジェクトにはありません。pnpm 12 では、pnpm dlx の後に --allow-build=esbuild を追加してください。pnpm 12 は、承認されていない esbuild のインストールスクリプトを実行しないためです。
変更をコーディングエージェントに任せる場合は、--claude または --codex を追加します:
npx blume@latest upgrade --claudepnpm dlx blume@latest upgrade --claudeyarn dlx blume@latest upgrade --claudebunx blume@latest upgrade --claudenubx blume@latest upgrade --claudeaube dlx blume@latest upgrade --claudeエージェントは、検出結果とこのガイドを読み込んだ状態で対話モードで起動します。各変更を適用し、blume doctor と blume build の両方が成功するまで実行を繰り返します。すべての編集はエージェント自身の権限フローを通るため、1 つずつ確認できます。インストールせずに package.json のバージョンだけを上げるには、--no-install を渡します。
以下のセクションでは、変更点を 1 つずつ説明します。手動でアップグレードするときや、エージェントが行った変更を確認するときに参照してください。
検索
search には、provider 文字列と認証情報のブロックの代わりに、blume/search のアダプターを渡します。デフォルトのローカル検索は変更不要です。
export default defineConfig({
search: {
provider: "algolia",
algolia: { appId: "APP_ID", indexName: "docs", searchApiKey: "SEARCH_KEY" },
},
});import { defineConfig } from "blume";
import { algolia } from "blume/search";
export default defineConfig({
search: algolia({ appId: "APP_ID", indexName: "docs", apiKey: "SEARCH_KEY" }),
});- Orama Cloud、Typesense、Mixedbread も同じように、それぞれ
oramaCloud()、typesense()、mixedbread()に置き換えます。キーを受け取るアダプターでは、検索専用キーの名前はすべてapiKeyです。mixedbread()はクエリをドキュメントサーバー上で実行するため、キーではなくstoreIdを受け取ります。それ以外のオプションはストア検索の呼び出しにそのまま渡され、top_kのデフォルトは 8 です。管理者キーはこれまでどおり環境変数(ALGOLIA_ADMIN_API_KEY、ORAMA_PRIVATE_API_KEY、TYPESENSE_ADMIN_API_KEY、MIXEDBREAD_API_KEY)に設定します。 provider: "pagefind"はpagefind()に、provider: "none"はsearch: falseになります。popularリンクやindexingオプションを残すには、アダプターを次のようにラップします:search: { provider: algolia({ … }), popular: […] }。
デプロイ
deployment には、adapter と output フィールドの代わりに、blume/deploy のホストアダプターを渡します。site と base はアダプターのオプションに移動します。
export default defineConfig({
deployment: {
adapter: "vercel",
output: "server",
site: "https://docs.example.com",
},
});import { defineConfig } from "blume";
import { vercel } from "blume/deploy";
export default defineConfig({
deployment: vercel({ site: "https://docs.example.com" }),
});netlify()、cloudflare()、node()も同じように使います。ホストアダプターを指定すると、サーバー出力に切り替わります。静的ビルドのまま、そのホスト向けのプラットフォームファイルも出力したい場合は、output: "static"を渡します。siteまたはbaseだけを設定している場合は、変更不要です。deployment: { site, base }は今後も静的ビルドの書き方です。redirectsには完全一致のパスを指定します。fromやtoに:paramセグメントや*ワイルドカードが含まれていると、検証エラーになるようになりました。Blume 1 もパターンをサポートしておらず、ホストによって扱いが異なっていました。パターンを使うルールは、ホスト側の設定(vercel.json、_redirects)に移してください。blume buildの--adapter、--output、--baseフラグは廃止されました。いずれかを渡すとビルドはエラーで停止し、代わりに使うdeploymentの設定が表示されます。アダプターはblume.config.tsで明示的に指定してください。サーバー出力をプラットフォームの環境から推測する動作はなくなりました。
各アダプターのオプションについては、デプロイ を参照してください。
コンテンツソース
content.sources の各エントリーは、{ type } オブジェクトではなく blume/sources のアダプターで指定します。
export default defineConfig({
content: {
sources: [
{ type: "filesystem", root: "content" },
{
type: "github-releases",
owner: "acme",
repo: "sdk",
prefix: "changelog",
},
],
},
});import { defineConfig } from "blume";
import { filesystem, githubReleases } from "blume/sources";
export default defineConfig({
content: {
sources: [
filesystem({ root: "content" }),
githubReleases({ owner: "acme", repo: "sdk", prefix: "changelog" }),
],
},
});mdx-remote、sanity、notion、obsidianは、それぞれmdxRemote()、sanity()、notion()、obsidian()になります。その他のフィールドは、そのまま呼び出しの引数に移します。{ type: "custom", source }はcustom(source)になります。content.root、content.include、content.excludeは、フォルダーが 1 つだけの場合の省略形として引き続き使えます。ただし、sourcesと一緒には使えなくなりました。併用している場合は、filesystem()エントリーに移してください。githubReleases()のリリースページは、1 つの言語でのみ公開されるようになりました。そのため多言語サイトでも、他のロケールの URL(/de/changelog/…)にはコピーされません。外部サイトがそれらのコピーにリンクしている場合は、デフォルトロケールのページへの リダイレクト を追加してください。
API リファレンス
トップレベルの openapi、asyncapi、graphql ブロックは、blume/reference のアダプターを並べた 1 つの reference リストにまとめられます。enabled は削除してください。
export default defineConfig({
openapi: { enabled: true, spec: "./openapi.yaml" },
graphql: {
enabled: true,
spec: "./schema.graphql",
endpoint: "https://api.example.com/graphql",
},
});import { defineConfig } from "blume";
import { graphql, openapi } from "blume/reference";
export default defineConfig({
reference: [
openapi({ spec: "./openapi.yaml" }),
graphql({
spec: "./schema.graphql",
endpoint: "https://api.example.com/graphql",
}),
],
});asyncapi: { … }は、オプションはそのままでasyncapi({ … })になります。- AsyncAPI 1.x または 2.x の仕様は、これまでどおり自動的に 3.0 に変換されます。ただし、コンバーターはオプションのピア依存関係になったため、プロジェクトに
@asyncapi/converterをインストールしてください。インストールしていない場合、ビルドはインストールコマンドを表示して失敗します。3.x の仕様では何もする必要はありません。 renderer: "scalar"は、リスト内で独立したscalar({ spec, theme, … })エントリーになります。ブロックのrouteとsourcesはそのまま引き継ぎます。enabled: falseのブロックは、リストに含めないだけで構いません。
アナリティクス
analytics オブジェクトは、blume/analytics のアダプターを並べたリストになります。
export default defineConfig({
analytics: {
posthog: { key: "phc_…" },
vercel: true,
},
});import { defineConfig } from "blume";
import { posthog, vercel } from "blume/analytics";
export default defineConfig({
analytics: [posthog({ key: "phc_…" }), vercel()],
});cloudflare: { token } は cloudflare({ token }) になり、scripts[] の各エントリーは script({ … }) になります。
Ask AI
ai.ask.provider には blume/ai のアダプターを渡します。モデルと、それに関連するフィールドはアダプター側で指定します。
export default defineConfig({
ai: {
ask: {
enabled: true,
provider: "openrouter",
model: "anthropic/claude-sonnet-4-5",
reasoning: "none",
},
},
});import { defineConfig } from "blume";
import { openrouter } from "blume/ai";
export default defineConfig({
ai: {
ask: {
enabled: true,
provider: openrouter({
model: "anthropic/claude-sonnet-4-5",
reasoning: "none",
}),
},
},
});使用できるアダプターは gateway()、openrouter()、llmgateway()、inkeep()、openaiCompatible({ baseUrl, name, model, apiKeyEnv }) です。model、apiKeyEnv、baseUrl、headers、reasoning はアダプターに移動します。enabled、instructions、retrieval、suggestions、cors、endpoint は ai.ask に残ります。provider を指定しない場合は、これまでどおり AI Gateway が使われます。
エージェントとその他の設定の移動
機械可読な設定は ai から新しい agents キーに移動します。また、3 つの小さなフィールドの形式が変わります。
export default defineConfig({
ai: { mcp: { enabled: true }, skills: "./skills" },
lastModified: true,
markdown: {
codeBlocks: { theme: { light: "github-light", dark: "github-dark" } },
},
theme: { layout: "sidebar" },
});export default defineConfig({
agents: { mcp: { enabled: true }, skills: "./skills" },
lastModified: "git",
markdown: {
code: { theme: { light: "github-light", dark: "github-dark" } },
},
});ai.api、ai.catalog、ai.llmsTxt、ai.markdownComponents、ai.mcp、ai.skills、ai.webBotAuth、ai.webmcpはagents.*に移動します。seo.agentReadabilityとseo.contentSignalsも同様です。aiに残るのはaskとopenInChatだけです。lastModifiedには単純な値を指定します。trueは"git"になり、{ type: "git" }や{ type: "frontmatter" }はその文字列だけを指定します。markdown.codeBlocksはmarkdown.codeに統合されます。theme.layoutは廃止されました。もともと参照されていなかったため、削除してください。
フロントマター
フロントマターのフィールドが 1 つ廃止されました: search.boost です。Blume 1 では指定できましたが、検索では一度も使われておらず、指定してもページの順位は変わりませんでした。使用している箇所はすべて削除してください。削除していないページはヒント付きの検証エラーになり、blume upgrade はその箇所をファイルと行とともに一覧表示します。
コンポーネントのオーバーライド
Blume 2 では、components.ts のすべてのエントリーを、実行時にフォールバックするのではなくビルド前にチェックします。mdx と layout の各エントリーには、インポートしたコンポーネント、パス文字列、{ component, client, media } オブジェクトのいずれかを指定する必要があります。また、islands グループは廃止されました。client モードを指定した mdx エントリーがアイランドになります。
import { defineComponents } from "blume";
import Counter from "./islands/Counter.tsx";
export default defineComponents({
islands: { Counter },
});import { defineComponents } from "blume";
import Counter from "./islands/Counter.tsx";
export default defineComponents({
mdx: { Counter: { component: Counter, client: "visible" } },
});インライン関数、components.ts 内で宣言したコンポーネント、スプレッド構文、計算されたキーは、BLUME_COMPONENTS_INVALID エラーになり、該当するエントリーが表示されます。コンポーネントを別のファイルに移し、そこからインポートしてください。islands/ フォルダーの規約はこれまでどおり使えます。指定できる形式については、カスタマイズ を参照してください。
イジェクトしたアプリ
Blume 1 で イジェクト したアプリは Blume CLI では実行されなくなりますが、blume パッケージには引き続き依存しています。ページは Blume のコンポーネントをインポートしています。src/generated/ には、Blume 1 のジェネレーターが出力したサイトのスナップショットが入っています。さらに astro build は、検索インデックス、llms.txt、サイトマップを出力するために blume.config.ts を読み込み直します。この状態で blume だけを 2 に上げると、Blume 1 のスナップショットが、新しい形式を前提とする Blume 2 のコンポーネントと組み合わさってしまいます。そのため、以下の手順でイジェクトし直してください:
Copy the project out
astro.config.mjs、src/、.blume/、dist/、node_modules/
以外のすべてを空のフォルダーにコピーします。コンテンツ、blume.config.ts、components.ts、islands/、public/、リファレンスが読み込む仕様ファイル、package.json
が対象です。イジェクトしたアプリには手を加えないでください。
Upgrade the copy
コピー先で npx blume@latest upgrade
を実行し、一覧表示された変更を適用して、blume.config.ts と components.ts
を Blume 2 の形式にします。その後、npx blume build
を実行し、イジェクトする前にサイトをビルドできることを確認します。
Eject a fresh copy
コピー先で npx blume eject --yes
を実行し、追加されたパッケージをインストールしてから、npm run build
でビルドします。
Carry your edits across
新しく生成された astro.config.mjs と src/
を、イジェクト済みのアプリと差分比較し、自分で加えた変更を新しいファイルに移します。
新しいコピーの準備ができるまでは、イジェクト済みのアプリは Blume 1("blume": "^1")のままにしておき、そこで blume upgrade を実行しないでください。バージョンを上げない限り、何も変わりません。
コマンドラインフラグ
Blume 1 では、コマンドが受け付けないフラグは無視されていましたが、今後はすべての blume コマンドがエラーにします。不要なフラグやスペルミスのあるフラグを渡しているスクリプトや CI のステップは失敗し、認識されなかったフラグと、そのコマンドで使えるフラグが表示されます。blume upgrade が検出するのは、削除された 3 つの blume build フラグ(--adapter、--output、--base)だけです。他の blume スクリプトも確認してください。
作業を確認する
blume upgrade が変更の必要な箇所はもうないと報告したら、サイトのチェックを実行します:
npx blume doctor
npx blume build
すべての変更点と、それぞれの変更理由は 変更履歴 に掲載しています。