コンテンツにスキップ
Blume
Esc
↑↓移動↵開く⌘Jプレビュー
このページの内容

デプロイ

設定不要で静的ドキュメントを任意のホストにデプロイできます。動的な挙動が必要な場合は、blume/deploy のホストアダプターを指定してサーバーサイドレンダリングに切り替えられます。

どこにでもデプロイ(静的)

blume build はドキュメントを素の HTML、CSS、そしてローカル検索インデックスとして dist/ にコンパイルします。実行するサーバーはありません — 任意の静的ホストにそのフォルダを向けるだけです。

設定 値
ビルドコマンド blume build
出力ディレクトリ dist
Node バージョン 22.19 以降

これらの設定は Vercel、Netlify、Cloudflare Pages、GitHub Pages、その他あらゆるバケットや CDN で動作します。ホストがビルドを実行できるよう、blume が依存関係に含まれていることを確認してください。

CloudFront の背後に Amazon S3 を置き、オリジンアクセスコントロール(origin access control)経由でプライベートバケットを読み取る構成では、さらに 2 つの設定が必要です。S3 の REST エンドポイントは各キーを完全一致で検索し、各ファイルをアップロード時に指定されたタイプで配信するためです:

  • ビューアーリクエストで実行される CloudFront Function。各ページの URL を、Blume がそのページ用に書き出す index.html にマッピングします: /quickstart は /quickstart/index.html に、/(または / で終わる任意のパス)はその index.html にマッピングします。最後のセグメントにドットを含むパス(/quickstart.md、/_astro/app.js)は変更せず、/.well-known/* にはこの関数を適用しないでください。その配下の api-catalog には拡張子がないためです。この関数がないと、S3 は /quickstart に対して 403 または 404 を返します。
  • ファイル拡張子からの推測では誤るか charset が付かないタイプを設定するアップロード: .md と .mdx には text/markdown; charset=utf-8、.txt には text/plain; charset=utf-8、.well-known/api-catalog には application/linkset+json; profile="https://www.rfc-editor.org/info/rfc9727" を設定します。ビルドに必要なすべてのルールは dist/_headers に記載されています。

S3 と CloudFront のガイド には、この関数を含む CloudFormation テンプレートと、これらのタイプを指定してアップロードするデプロイスクリプトが用意されています。

静的ビルドを静的アセットとして配信する Cloudflare Workers では、Wrangler の設定の assets 配下に "html_handling": "drop-trailing-slash" を設定してください。Blume は各ページを <route>/index.html として書き出し、末尾のスラッシュなしでリンクしますが、Cloudflare のデフォルト(auto-trailing-slash)は /quickstart に対して /quickstart/ への 307 を返します。cloudflare() のサーバービルド はすべてのページを Worker 経由でルーティングし、Worker はどちらの設定でも /quickstart を配信します。そのため、サーバービルドでこの設定が問題になるのは、ビルドが Could not wire Accept: text/markdown negotiation という警告を出し、静的レイヤーがページを直接配信する場合のみです。

静的ビルドには次のものが含まれます:

  • すべてのドキュメントページとカスタムページ(静的 HTML として)
  • ローカル検索インデックス(デフォルトは Orama、Pagefind はオプトイン)
  • サイト URL が判明している場合の sitemap.xml
  • robots.txt(サイト URL が判明している場合はサイトマップを指します)
  • AI ツール向けの llms.txt と llms-full.txt
  • リダイレクトページ
  • seo.og.enabled が有効な場合、事前レンダリングされた Open Graph 画像

サイト URL を設定する

サイトマップ、canonical タグ、RSS、Open Graph 画像には絶対オリジンが必要です。Vercel、Netlify、Cloudflare Pages では、Blume がビルド時にプラットフォームの環境から自動検出します — 設定は不要です。

検出された値を上書きする場合、またはそれを公開していないホスト(GitHub Pages、S3、カスタム CDN)で指定する場合は、site に http:// または https:// で始まる絶対 URL を設定します。静的ビルドでは、プレーンな deployment オブジェクトに設定します:

deployment: {
  site: "https://docs.example.com",
}

Vercel と Netlify では、自動検出の際に Blume はデプロイごとのプレビュー URL よりも安定した本番ドメインを優先するため、canonical オリジンはデプロイをまたいで変わりません。Cloudflare Pages が公開するのは現在のデプロイの URL(CF_PAGES_URL)のみで、これはデプロイのたびに変わるため、Cloudflare Pages では site を設定してください。Cloudflare Workers は URL を一切公開しないため、Workers でも site を設定してください。

blume dev の実行中、サイト URL が未設定の場合はローカル開発サーバー(例: http://localhost:4321)にフォールバックするため、サイト URL に依存する機能 — Open Graph 画像、canonical、サイトマップ — がそのまま動作します。ビルドではこのフォールバックは使われないため、本番の出力が localhost を指すことはありません。

モノレポ

ドキュメントのワークスペースを独立したプロジェクトとしてデプロイし、ホストのルートディレクトリをそのワークスペースに設定して(Vercel の Root Directory、Netlify の Base directory)、上記の設定を使ってください。Vercel では、ドキュメントがワークスペース外のファイルを読み取る場合 — コンポーネントの例 やインポートするワークスペースパッケージ、theme.css 内の @source パス、リポジトリ内の別の場所にある仕様ファイルなど — は、Include source files outside of the Root Directory in the Build Step をオンのままにしてください(デフォルトはオンです)。オフにすると、ビルドがそれらのファイルにアクセスできません。モノレポガイド では、pnpm と Turborepo を使ったセットアップを順を追って説明しています。

ローカルでプレビューする

公開する前に、静的ホストが配信するのとまったく同じ形で本番ビルドをプレビューしましょう:

blume build
blume preview

blume preview は静的ビルドと、node() および cloudflare() のサーバービルドを配信します。Vercel と Netlify のアダプターにはローカルのプレビューサーバーがないため、vercel() または netlify() のサーバービルドの後では、代わりにエラーを出して停止します。サイトを試すには blume dev を使うか、vercel deploy または netlify deploy でプレビューをデプロイしてください。

静的ビルドでは、blume preview は dist/ 内のファイルを配信するだけでなく、ホストと同じように応答します。ビルドが書き出すホスト用のファイルと同様に、パターンを含む リダイレクト を設定されたステータスで適用します。また、末尾のスラッシュも静的ホストと同じように処理します:

  • 末尾にスラッシュが付いたページの URL(/guide/)は、クエリ文字列を維持したままページ(/guide)にリダイレクトされます。
  • public/ に配置した HTML のフォルダー(public/demo/index.html)は /demo/ で配信され、/demo はそこにリダイレクトされるため、その中の相対リンクが正しく解決されます。

blume dev も末尾のスラッシュを同じように処理します。

サブパスへのデプロイ

example.com/docs のようなパス配下でドキュメントを配信しますか? base を設定してください — GitHub Pages のプロジェクトサイトでよくあるケースです。ルートを含むサイト全体がそのベース配下に移動し、内部リンクとアセット、そして生の HTML 内のルート相対の href や src(<a href="/guide">、<img src="/logo.png">)もベースを含むように書き換えられます。

deployment: {
  base: "/docs",
}

base(および site)は、すべてのホストアダプターのオプションでもあります: vercel({ base: "/docs" })。@astrojs/vercel はベースを無視するため、vercel() のサーバービルドは自ら静的ファイルを .vercel/output/static/docs/ に移動し、.vercel/output/config.json 内のルートとリダイレクトを /docs 配下に移します。

ベースと同じ名前のコンテンツフォルダー内にあるページでも、各ページはベース配下で自身のパスを維持します: base: "/docs" の場合、docs/setup.md は /docs/docs/setup で配信され、その canonical URL、サイドバーのリンク、llms.txt のエントリーもそこを指します。書いたルート相対のリンクがすでにベースで始まっている場合は、ベースを含むものとみなされ、書いたとおりに残されます。そのため、そのページへは相対リンク(./docs/setup)か完全なパス(/docs/docs/setup)でリンクしてください。

デプロイごとに異なるベース

blume.config.ts はモジュールなので、base を環境変数から取得できます。これにより、CI は設定を編集することなく、各プルリクエストのプレビューをそれぞれ独自のパス配下にビルドできます:

deployment: {
  base: process.env.DOCS_BASE,
}
DOCS_BASE=/pr-1234 blume build

DOCS_BASE が未設定の場合、サイトはルートにビルドされるため、本番では追加の設定は必要ありません。

ドキュメントをパス配下にマウントする

basePath は生成されるすべてのルートをあるセグメント配下(/docs/getting-started)にマウントしますが、サイドバーはそのままです — トップレベルはラッパーグループではなく、あなたのセクションのままです。ドキュメントは /docs/* に置きつつ、サイトのルートは自分のものとして残したい場合に使います(Docusaurus の routeBasePath や Fumadocs の baseUrl のようなものです)。

basePath: "/docs",

リンクはルートにマウントされている前提(/getting-started)で書いてください。Blume がリンクを書き換え、リダイレクト、サイトマップ、canonical URL、Open Graph 画像、llms.txt、検索インデックスも合わせて処理します。公開アセット(画像や public/ 配下のファイル)はサイトのルート、または base を設定している場合はその配下に残ります。

これは上記 2 つのパスとは別の概念です:

  • ソースごとの prefix は単一のソースに名前空間を与え、サイドバーグループを追加します。
  • deployment.base はアプリ全体が配信されるホスト側のサブディレクトリです。両者は組み合わせられます — 両方を設定すると、ページは {deployment.base}/{basePath}/page に配置されます。

サーバーレンダリング

静的出力でほとんどのドキュメントは事足ります。リクエスト時の機能 — 特に アシスタント エンドポイントと MCP サーバー — が必要な場合はサーバー出力に切り替えます。切り替えるにはホストを指定します: deployment には blume/deploy からインポートしたアダプターを渡します。

import { defineConfig } from "blume";
import { vercel } from "blume/deploy";

export default defineConfig({
  deployment: vercel(),
});

すべてのアダプターは同じ名前付きオプション — site、base、output — を受け取り、それ以外のものは基盤となる @astrojs/* アダプターにそのまま渡します。そのため、Blume が名前を定義していないオプションも確実に届きます:

deployment: vercel({
  site: "https://docs.example.com",
  // Passed straight to @astrojs/vercel.
  isr: { expiration: 60 },
}),
アダプター パッケージ 用途
vercel() @astrojs/vercel Vercel — 最も洗練された選択肢
netlify() @astrojs/netlify Netlify Functions
node() @astrojs/node セルフホストの Node サーバー、コンテナ
cloudflare() @astrojs/cloudflare Cloudflare Workers

vercel() と node() は Blume に同梱されています — 選ぶだけで動きます。netlify() と cloudflare() はプロジェクトへのパッケージのインストールが必要です(例: bun add -d @astrojs/netlify)。パッケージが見つからない場合、blume build はお使いのパッケージマネージャー用のインストールコマンドを表示して停止し、blume dev は警告を出し、blume doctor はそれを報告します。pnpm を使う場合は、これらのパッケージが持ち込むビルドスクリプトも、blume init が書き込む esbuild のエントリーと並べて pnpm-workspace.yaml の allowBuilds で承認してください: Netlify では sharp(アダプターが独自のコピーを持ち込むため)、Cloudflare では workerd です。pnpm 11 以降では承認するまで ERR_PNPM_IGNORED_BUILDS でインストールが停止し、pnpm 10 では警告を出してスクリプトをスキップします。allowBuilds には pnpm 10.26 以降が必要です。

アダプターを指定すると、ビルドはサーバー出力に切り替わります。そのホスト上で静的ビルドを維持する — ホストのサイト URL 検出や、ホストが読み取るプラットフォーム用ファイルは引き続き利用する — には、output: "static" を渡します:

deployment: netlify({ output: "static" }),

サーバービルドには静的ビルドのすべてに加えて、追加した Astro のエンドポイントやミドルウェアが含まれます。node() アダプターは、node dist/server/entry.mjs で直接実行できるスタンドアロンのサーバーを生成します。起動時に環境変数 HOST と PORT を設定しない限り、サーバーは localhost:4321 で待ち受けます(HOST=0.0.0.0 PORT=8080 node dist/server/entry.mjs)。node() に渡した host と port は効果がありません。@astrojs/node がそれらを Astro 自身のサーバー設定で置き換えるためです。リバースプロキシの背後では、レート制限 が閲覧者ごとに個別にカウントされるよう allowedDomains を設定してください。このサーバーはプロジェクトの node_modules へのリンクを通じてパッケージを解決するため、dist/ だけでなく、依存関係をインストールした状態のプロジェクトごとデプロイしてください。サイトがディスカバリーファイルを公開している場合、コンテンツソースがダウンロードした画像を配信する場合、またはリダイレクトを設定している場合、Blume は Astro のエントリー(同じ場所の astro-entry.mjs に移動されます)の手前に小さなラッパーを配置します。このラッパーは .well-known のディスカバリーファイルを適切なメディアタイプと CORS ヘッダー付きで配信し、ダウンロードした SVG をサンドボックス化して配信します。これらはスタンドアロンサーバーの静的ハンドラーだけではできないためです。また、各リダイレクトには設定されたステータスで応答します。

vercel() のサーバービルドは、アダプターがトレースした関数バンドルを調べ、インポートされているのにコピーされていないパッケージがないかを確認します。そのようなパッケージがあると、Vercel 上で関数がクラッシュするためです。自分でインポートしたものが欠けている場合は警告になります。Blume の依存関係が欠けている場合はビルドが停止し、ビルドは .vercel/output/config.json を削除します。これにより、Blume が追加するルートを欠いた出力を vercel deploy --prebuilt でデプロイできないようにします。

cloudflare() のサーバービルドは Cloudflare Workers でのみ動作します。@astrojs/cloudflare がバージョン 13 で Cloudflare Pages のサポートを終了したためです。静的ビルドはこのパッケージを読み込まないため、その dist/ は引き続き Pages にデプロイできます。サーバービルドは、blume build の後にプロジェクトのルートで npx wrangler deploy を実行してデプロイします: Blume は Wrangler のリダイレクト設定(redirected config)を .wrangler/deploy/ に書き出し(.gitignore に .wrangler/ も追加します)、Worker にはプロジェクトに基づいた名前を付けます — package.json の name、なければサイトのホスト名、それもなければフォルダー名です — ただし、プロジェクトのルートに置いた独自の wrangler.jsonc で name を設定している場合を除きます。

Vercel と Cloudflare では、サーバービルドによって Accept: text/markdown のコンテンツネゴシエーション も有効になり、そのヘッダー付きで任意のコンテンツページをリクエストしたエージェントは、同じ URL で生の Markdown 版を受け取れます。Vercel では、Blume がデプロイのルーティング設定にヘッダー条件付きのリライトを挿入します。Cloudflare では、Astro の Worker の手前に小さな Worker を生成し、フィンガープリント付きのビルドアセットと生の .md、.txt、.json、.well-known ファイルを除くすべてのパスに assets.run_worker_first を適用します — そうしないと、プラットフォームはサーバーコードが実行される前に事前レンダリング済みページ(および対応するページがない URL に対しては 404.html)を配信してしまうためです。除外されたファイルは Worker を介さない高速パスを維持します。また、事前レンダリング済みのページごとの JSON ドキュメント(/api/docs/pages/{route}.json)へのリクエストがこの Worker に届いた場合も、Worker がアセットバインディングから応答します。そうしないと、Astro がそのリクエストを /api/ のキャッチオールにルーティングしてしまうためです。

非公開のドキュメント

Blume 自体にはサインイン機能がありません。静的ビルドは単なるファイルの集まりであり、ホストにアクセスできる人なら誰でも dist/ 内のあらゆるものを取得できます。サイトを非公開にするには、ホストのアクセス保護を有効にしてください。アクセス保護は、ファイルが配信される前にすべてのリクエストをチェックします:

  • Vercel: Deployment Protection を All Deployments スコープで有効にすると、プレビューだけでなく本番も保護されます。Vercel Authentication では Vercel チームのメンバーがアクセスでき、Password Protection(有料プラン)では共有パスワードを知っている人なら誰でもアクセスできます。
  • Netlify: すべてのデプロイに パスワード保護 を設定します。共有パスワードを使うか、Enterprise プランではチームログインを使います。
  • Cloudflare: サイトを配信する Worker に Cloudflare Access を設定します(Workers & Pages から対象の Worker を開き、Access を選択)。これにより、その Worker が応答するすべてのドメインが保護されます。サインインできる人は、メールアドレス、メールドメイン、または Cloudflare アカウントのメンバーシップで指定します。
  • GitHub Pages: GitHub Enterprise Cloud 上の Organization からサイトをプライベートに公開すると、リポジトリへの読み取りアクセス権を持つ人だけが閲覧できるようになります。
  • 自前のサーバー: nginx の auth_basic や ID 認識型プロキシ(identity-aware proxy)など、dist/ の手前に認証を置きます。

ホストの保護は サーバービルド でも同じように機能します。保護はサイト全体に適用されるため、一部のページを公開したままにするには、それらを別のサイトとして公開してください。

ページ、検索インデックス、.md のコピー、llms.txt、Open Graph 画像など、Blume が dist/ に書き出すものはすべて保護の内側に置かれます。ただし、いくつかの機能は保護の外側に及びます:

  • ホスト型の 検索プロバイダー(Algolia、Orama Cloud、Typesense、Mixedbread)は、コンテンツのコピーをそのサービス上に独自に保持します。組み込みの Orama、FlexSearch、Pagefind のインデックスは dist/ 内のファイルなので、非公開のままです。
  • 保護の外側にあるサービスはページを読み取れません。Open in chat は ChatGPT や Claude に開けないリンクを渡すことになり、Slack や X のリンクプレビューには Open Graph カードが表示されず、エージェントは llms.txt や MCP サーバーを読み取れません。チャットのアクションを非表示にするには ai.openInChat: false を設定してください。

リダイレクト

blume.config.ts で古い URL を新しい URL にマッピングします:

redirects: [{ from: "/old", to: "/new", status: 301 }],

status は 301、302、307、308 を受け付けます(デフォルトは 301)。サーバービルドではリダイレクトをリクエスト時に、設定されたステータスで処理します。blume dev と blume preview も同様です。静的ビルドではリダイレクトページに加えてホストが読み取るプラットフォーム用のファイルも出力するため、ホストが本物の HTTP リダイレクトを返せます: netlify() と cloudflare() には _redirects、vercel() には vercel.json、そしてホストを指定していない場合はその両方に加えて blume-redirects.json — その他の環境(nginx/Apache のルール、エッジワーカーなど)向けの構造化マニフェストです。public/ に配置した _redirects や vercel.json はそのまま維持されます。

あるページを別のページへ移動するリダイレクトは、そのページの 生の Markdown も一緒に移動します: blume dev とすべてのビルドで、/old.md と /old.mdx は同じステータスで /new.md と /new.mdx にリダイレクトされます。ただし、移行元のサイトの /old.html のような .html の URL からのリダイレクトでは、生の Markdown は移動しません。その URL には Markdown のコピーが存在したことがないためです。Markdown の URL がすでにコピーを配信しているリダイレクトでも移動しません: /index.md はホームページのコピーなので、/index から / へのリダイレクトではそのまま残ります。

/guide/index.html から /guide へのリダイレクトのように、ページ自身の index.html の URL からのリダイレクトには、静的ビルドではリダイレクトページが作られません。そのファイルにはページ自体が書き出されるためです。リダイレクト用のファイルを読み取るホストは、リダイレクトで応答します。それ以外のホストは、その URL でページを配信します。

Blume が自ら追加するリダイレクトが 1 種類あります: 以前のバージョンでより短い URL で公開されていた日付名のページ(例えば /changelog/05-2022 で公開されていた changelog/12-05-2022.mdx)は、その URL から自身の URL へリダイレクトされます(数値プレフィックスによる並び替え を参照)。古い URL に別のページが存在する場合や、設定したリダイレクトがすでにその URL から始まっている場合は追加されません。

次の 2 つのホストでは、ファイルを出力するだけでは不十分です:

  • Netlify は、ルールが強制(force)されていない限り、リダイレクトルールよりも実在するファイルを優先して配信します。そして静的ビルドでは、すべての from にリダイレクトページが存在します。netlify() 用の _redirects はルールを強制します(/old /new 301!)。Cloudflare はこのフラグを受け付けないため、ホストを指定していないビルドが書き出すファイルにはこのフラグが付かず、Netlify 上ではそのビルドは代わりにリダイレクトページで応答します。HTTP リダイレクトを返すには、netlify({ output: "static" }) でホストを指定してください。
  • Vercel は vercel.json をプロジェクトのルートディレクトリから読み取り、出力ディレクトリからは読み取りません。そのため、dist/ 内のコピーが適用されるのは、Vercel CLI でそのフォルダー自体をデプロイした場合(vercel deploy dist)のみです。Git 連携したプロジェクトはこのファイルを読み取らず、リダイレクトページを配信し、コンテンツタイプ のヘッダーも一切適用されません。dist/vercel.json の redirects と headers をプロジェクトのルートディレクトリにある vercel.json にコピーするか、vercel() でサーバービルドを使用してください。サーバービルドでは、ルーティング設定にリダイレクトとディスカバリー用のヘッダーが含まれます。

パターンリダイレクト

from は、Mintlify や vercel.json と同じ書き方で、複数のパスを一度にカバーできます:

redirects: [
  { from: "/beta/:slug*", to: "/v2/:slug*" },
  { from: "/blog/:slug", to: "/articles/:slug" },
  { from: "/articles/concepts-*", to: "/concepts" },
  { from: "/old/article-*", to: "/new/article-*" },
],
  • :name は 1 つのセグメント全体にマッチします: /blog/:slug は /blog/hello にはマッチしますが、/blog/a/b にはマッチしません。
  • 最後のセグメントに置いた :name* は、パスの残りの部分(任意の数のセグメント)にマッチします: /beta/:slug* は /beta/guides/setup を /v2/guides/setup に、/beta 自体を /v2 に転送します。最後のセグメントが * の場合も同じです。この /beta だけのパスは、どのホストにも独立したルールとして渡されるため(_redirects では /beta /v2)、すべてのホストで同じ場所に転送されます。blume audit は転送先を確認し、ビルドが配信していない /v2 へ /beta が転送される場合は、壊れたリダイレクトとして報告します。
  • セグメントの末尾にある * は、その位置以降のパスの残りの部分にマッチします: /articles/concepts-* は /articles/concepts-overview にマッチします。

to では、キャプチャを名前でセグメント全体として(/:slug*、/:slug)参照するか、* で from の * がマッチした部分を参照します(_redirects での表記である :splat でも参照できます)。キャプチャを参照しない to は、パターンがカバーするすべてのパスを 1 つのページに転送します。同じパスをカバーするパターンよりも完全一致のリダイレクトが優先され、パターンは記述した順に試されます。

各ホストには、それぞれの構文でパターンが渡されます: _redirects ではスプラット、vercel.json では path-to-regexp 形式のソース、そして vercel() または netlify() のサーバービルドではルーティング設定です。node() と cloudflare() のサーバーは自身でパターンをマッチングし、blume dev と blume preview も同様です。静的ビルドはパターンに対してリダイレクトページを書き出しません。パターンがカバーするすべてのパスに 1 ページずつ必要になるためです。そのため、これらのファイルをいずれも読み取らないホスト(GitHub Pages など)では、完全一致のリダイレクトのみが適用されます。blume-redirects.json には、パターンが記述したとおりに記載されます。

blume validate は、各リダイレクトの転送先を確認します。完全一致の to は、ページ、public/ 内のファイルまたは Blume が生成するファイル、あるいは別のリダイレクトの from でなければなりません。パターンの場合は、to の最初のキャプチャより前のリテラル部分(/v2/:slug* の /v2/)の配下で何かが配信されている必要があります。どこにも行き着かないリダイレクトは、その to に対して BLUME_BROKEN_REDIRECT の警告を出します。blume audit は、ビルドされたサイト上ですべてのリダイレクトを実際にたどります。

パターンがページにもマッチすることはできません: 両者のどちらが応答するかはホストによって異なるため、ビルドはそのページを示して BLUME_REDIRECT_MATCHES_PAGE で停止します。パターンを移動したパスだけに絞り込んでください。ページ自身の URL からの完全一致のリダイレクトはどのホストでも同じように応答し、その URL を引き継ぐためページは公開されません。そのため、この場合は同じコードが警告として出されます: ページを移動した場合はページを削除し、そうでなければリダイレクトを削除してください。/guide.md やホームページの /index.md のような、ページの Markdown コピーからのリダイレクトも同様に警告となります。そのコピーがエージェントから利用できなくなるため、リダイレクトを削除してください。

コンテンツタイプ

ホストが読み取る場合、ビルドでは _headers ファイルも出力され、生の AI 対応エンドポイント — /<route>.md、/<route>.mdx、および .txt ファイル(llms.txt、llms-full.txt)— に charset=utf-8 を固定します。これらのレスポンスは妥当な UTF-8 ですが、多くの静的ホストは charset なしの text/markdown / text/plain として配信し、ブラウザは Windows-1252 にフォールバックします — その結果、非 ASCII のドキュメント(日本語、アクセント付きラテン文字など)は生の URL を直接開いたときに文字化けします。HTML ページは <meta charset> を持つため影響を受けません。Netlify は静的デプロイで、Cloudflare(Pages と Workers の静的アセット)は静的ビルドとサーバービルドの両方で _headers を読み取るため、これらのアダプターとホストを指定していない静的ビルドではこのファイルが出力されます。Vercel(ヘッダーはルーティング設定で扱われます)と Node(サーバーがこのファイルを無視します)では出力されません。Netlify のサーバービルドでは、代わりに Frameworks API の設定(.netlify/v1/config.json)の headers に同じルールを書き込みます。Vercel の静的ビルドでは、代わりに dist/vercel.json に同じルールを書き込みますが、Git 連携したプロジェクトはこのファイルを読み取りません(リダイレクト を参照)。public/ に配置した _headers はそのまま維持されます。

Powered-by ヘッダー

Blume は X-Powered-By: Blume レスポンスヘッダーで自身の名前を示すため、HTTP インスペクターや技術検出ツールはサイトが何でビルドされたかを判別できます。このヘッダーを省くには、poweredBy を false に設定してください:

poweredBy: false,

blume dev はすべてのレスポンスでこのヘッダーを送信します。サーバービルドでは、ホストがヘッダーを取得する場所からこのヘッダーが送信されます: node() のサーバーと cloudflare() の Worker は自らヘッダーを設定し、vercel() のビルドはルーティング設定に、netlify() のビルドは Frameworks API の設定のヘッダールールにこのヘッダーを含め、オンデマンドでレンダリングされるページには Blume のミドルウェアがこのヘッダーを追加します。静的ビルドでは コンテンツタイプ と並べて _headers と dist/vercel.json に記載されるため、これらのファイルが適用されるホストでのみ送信されます: Git 連携した Vercel プロジェクトや、GitHub Pages のようにカスタムヘッダーを送信しないホストでは送信されません。

イジェクト したアプリでは、astro.config.mjs 内の blumeIntegration() の poweredBy オプションで切り替えます。そのビルドでは、サーバーレンダリングされたページと _headers からヘッダーが送信されます。それ以外の場所でヘッダーを付与するサーバーエントリーのラッパーやルーティング設定は、blume build が行うステップです。

環境変数

機能が実行時のシークレットを必要とする場合、それが欠けていると Blume は blume dev/build の時点で警告します — 最初のリクエスト時ではなく、早い段階で問題が表面化します:

機能 変数
アシスタント(AI Gateway) AI_GATEWAY_API_KEY(または Vercel OIDC)
アシスタント(その他のアダプター) アダプターのデフォルトのキー環境変数(OPENAI_API_KEY、ANTHROPIC_API_KEY、GEMINI_API_KEY、XAI_API_KEY、OPENROUTER_API_KEY、LLMGATEWAY_API_KEY、INKEEP_API_KEY)、またはアダプターに渡した apiKeyEnv
アシスタントのボット対策 TURNSTILE_SECRET_KEY(turnstile())、HCAPTCHA_SECRET_KEY(hcaptcha())
レート制限(upstash()) UPSTASH_REDIS_REST_URL と UPSTASH_REDIS_REST_TOKEN
レート制限(unkey()) UNKEY_ROOT_KEY、または unkey() に渡した rootKeyEnv
Mixedbread 検索 MIXEDBREAD_API_KEY
ナレーション(生成音声) gateway() には AI_GATEWAY_API_KEY(または Vercel OIDC)、openai() には OPENAI_API_KEY(baseUrl を指定した場合は、変数名を指定しない限り不要)、またはいずれかに渡した apiKeyEnv
コンテンツソース NOTION_TOKEN(notion())、SANITY_TOKEN(sanity())、CONTENTFUL_ACCESS_TOKEN(contentful()。--preview には CONTENTFUL_PREVIEW_TOKEN も必要で、ない場合は失敗します)、PAYLOAD_API_KEY(payload())、STRAPI_API_TOKEN(strapi())、GITHUB_TOKEN(githubReleases()、および github を指定した mdxRemote())

ローカル開発では .env.local に、本番ではホストの環境に設定してください。コンテンツソースは blume dev と blume build の実行中、コンテンツを取得する際にトークンを読み取り、ナレーションは blume build の実行中にキーを読み取るため、これらはサイトをビルドする環境に設定してください。検索インデックスの同期に必要なビルド時のシークレット(ALGOLIA_ADMIN_API_KEY、ORAMA_PRIVATE_API_KEY、TYPESENSE_ADMIN_API_KEY)は、同期ステップ自体がチェックします: 未設定の場合、ビルドは警告を出して同期をスキップし、設定されている場合は、同期が失敗すると ビルドも失敗します。GitHub info カードも、GITHUB_TOKEN が設定されている場合は GitHub の API レート制限を緩和するためにそれを送信します。

ビルドキャッシュ

Blume は、ビルドで再利用できる 2 つのキャッシュを保持します。Astro と Vite のキャッシュは .blume/.cache/ 配下に置かれます(コンテンツストアや画像変換など)。レンダリング済みの OG カード は node_modules/.cache/blume/og に置かれるため、再ビルド時にはタイトル、説明、ブランディングが変更されたカードだけがレンダリングされます。デプロイ間でこのディレクトリが保持されるかどうかはプラットフォームによって異なります:

  • Vercel はビルドキャッシュから node_modules/** を復元するため、カードは引き継がれます(キャッシュは 1 GB で 1 か月間保持され、ブランチごとにキーが分かれます — 新しいブランチは本番のキャッシュから開始します)。
  • Netlify は node_modules を復元するため、カードは引き継がれます。
  • Cloudflare Workers Builds が保持するのはパッケージマネージャーのキャッシュと、Astro プロジェクトとして検出された場合の node_modules/.astro のみです — node_modules/.cache は保持されません — そのため、デプロイのたびにすべてのカードがレンダリングされます。
  • GitHub Actions やその他の自前で管理するランナーは、自分でディレクトリをキャッシュしない限り何も保持しません:
- uses: actions/cache@v6
  with:
    path: node_modules/.cache/blume/og
    key: blume-og-${{ runner.os }}-${{ hashFiles('**/bun.lock', '**/package-lock.json', '**/pnpm-lock.yaml') }}
    restore-keys: blume-og-${{ runner.os }}-

カードはコンテンツをキーにしているため、キーが厳密でなくても問題ありません。復元されたキャッシュはレンダリングを省くだけで、誤ったカードを配信することはありません。

どのプラットフォームでもキャッシュを破棄してしまうインストールコマンドが 1 つあります: npm ci はインストール前に node_modules を削除します。キャッシュを再利用するには、インストールコマンドとして npm install、bun install、pnpm install のいずれかを使ってください。

ビルドサマリー

ビルドのたびにサマリーが出力されます — 出力モード、アダプター、解決されたサイト URL、検索プロバイダー、リダイレクト数、サイトマップと llms.txt の状態、有効になっているサーバー機能 — デプロイ前に、何が反映されたのか(自動検出されたものも含めて)を確認できます。

最終更新

このページは役に立ちましたか?