コンテンツソース
ローカルファイル、リモートリポジトリ、CMS、または任意のカスタムバックエンドからドキュメントを取得し、複数のソースをビルド時に読み込む1つのスタティックファーストなサイトに統合できます。
Blume はデフォルトで .md/.mdx ファイルのフォルダーを読み込みます。コンテンツソースを使うと、リモートリポジトリ、CMS、任意のカスタムバックエンドなど、別の場所からページを取得し、複数のソースを1つのサイトに統合できます。ソースはビルド時に読み込まれ、Blume はスタティックファーストのままです。
デフォルトの動作
設定を行わない場合、Blume はコンテンツルート(デフォルトでは docs)を1つのファイルシステムソースとしてスキャンします。トップレベルの content.root、content.include、content.exclude オプションはその単一ソースの省略記法であり、インポートするものも変更するものもありません。
import { defineConfig } from "blume";
export default defineConfig({
content: { root: "docs" },
});
アダプター
content.sources の各エントリはアダプターです。アダプターは blume/sources からインポートするファクトリーで、Blume がビルド時に読み込むプレーンなディスクリプターを返します。ソースを組み合わせるには sources 配列を追加します。sources が存在する場合は暗黙のデフォルトが置き換えられるため、ローカルドキュメント用に filesystem() エントリを含め、root、include、exclude をそこへ移動してください。省略記法と sources は併用できません。その場合、Blume はどのフィールドを移動すべきかを報告します。
import { defineConfig } from "blume";
import { filesystem, mdxRemote } from "blume/sources";
export default defineConfig({
content: {
sources: [
// Local docs at the site root
filesystem({ root: "docs" }),
// Remote MDX from a GitHub repo, mounted under /sdk
mdxRemote({
prefix: "sdk",
github: { owner: "acme", repo: "sdk", ref: "main", path: "docs" },
}),
],
},
});
filesystem() 以外の各組み込みアダプターにはそれぞれ専用のページがあり、それ以外のバックエンドは custom() で組み込めます。
| アダプター | 読み込む対象 | ランタイム依存関係 | 環境変数 |
|---|---|---|---|
obsidian() |
Obsidian の Vault(その場で読み込み) | — | — |
mdxRemote() |
GitHub リポジトリまたは raw URL の .md/.mdx |
— | GITHUB_TOKEN(プライベートリポジトリ) |
githubReleases() |
リポジトリのリリース(変更履歴エントリとして) | — | GITHUB_TOKEN(プライベートリポジトリ) |
sanity() |
Sanity データセットに対する GROQ クエリ | @sanity/client |
SANITY_TOKEN(プライベートデータセット) |
notion() |
Notion のデータベース | @notionhq/client |
NOTION_TOKEN |
contentful() |
Contentful の1つのコンテンツタイプ | — | CONTENTFUL_ACCESS_TOKEN |
payload() |
Payload のコレクション | — | PAYLOAD_API_KEY |
strapi() |
Strapi のコンテンツタイプ | — | STRAPI_API_TOKEN |
custom() |
自分で実装した任意の ContentSource |
— | — |
オプションオブジェクトを受け取るすべてのアダプターは、2つの共通オプションを受け付けます。
prefixはソースのルートを/<prefix>/…の下に名前空間として分けます。この値は、診断メッセージにおけるソース名およびキャッシュディレクトリ名にもなります。2つのソースが同じルートに解決される場合、Blume はBLUME_DUPLICATE_ROUTEビルドエラーを報告します。各ソースには異なるprefixを指定してください。pollInterval(秒)を設定すると、開発環境でリモートソースがその間隔で再取得を行い、コンテンツが実際に変更された場合にのみリロードします。未設定のままにすると、一度だけ取得してそのセッション中は固定されます。ローカルソース(filesystem()、obsidian())は代わりにファイルシステムを監視するため、このオプションは無視されます。
アダプターのディスクリプターは、必要とする SDK と読み込む環境変数も宣言します。そのため、生成されるプロジェクトはそのパッケージを宣言し、blume dev、blume build、blume doctor は変数が未設定の場合に警告を出し、blume doctor は設定済みのソースを一覧表示します。この警告はどのソースの取得よりも前に表示されるため、その後に取得が失敗しても埋もれることはありません。notion() と contentful() はトークンがないと何も読み込めないため、トークンが未設定の場合は最初のリクエストの前に BLUME_MISSING_SECRET エラーで停止します。同様に、SDK がインストールされていないソースは BLUME_SOURCE_SDK_MISSING で停止します。いずれの場合も、キャッシュされたスナップショットがあれば代わりにそれを提供します。オプションは設定の読み込み時に検証されます。必須オプションの欠落、不明なキー、または 1.x の { type: "…" } オブジェクトの残存があると、修正方法を示すメッセージとともに失敗します。
filesystem() ソースが1つだけの場合、生成されるドキュメントコレクションはそのソース自身のディレクトリをルートとします。複数のファイルシステムソースは1つのルートを共有し、include の glob でそれを分割する必要があります。別の場所をルートとする2つ目のソースは BLUME_ENTRY_ID_MISMATCH として報告されるため、そのページが気づかないうちに 404 になることはありません。
キャッシュとオフラインビルド
各リモートソースは .blume/cache/<source>/ 配下にスナップショットを保持します。ネットワークの一時的な不調や CMS の障害などで取得に失敗した場合、Blume はビルドを失敗させる代わりに、警告を出しつつ最後に取得できた正常なスナップショットを提供します。プレビュー用と公開済みのコンテンツは別々のスナップショットを持ち、ソースオプションの組み合わせごとにも別々のスナップショットが作られます。そのため、ビルドが --preview で取得した下書きにフォールバックすることはなく、ソースの query や fields を編集すると新たに取得し直します。ただし、custom() ソースは例外で、スナップショットはプレビューモードごとにのみ保持されるため、オプションを編集した後は blume sync を実行してください。キャッシュは .blume/ 内に置かれ、再生成されるものであり、コミットすることはありません。
開発環境では、リモートソースはスナップショットがあればそこから提供されるため、開発サーバーを再起動しても再取得されません。最新のコンテンツを取得するには blume sync を実行するか(起動中の開発サーバーはホットリロードします)、先にスナップショットを破棄するには blume sync --force を実行してください。ローカルのファイルシステムソースは通常どおりホットリロードされます。代わりにリモートソースの変更をポーリングするには、そのソースに共通オプションの pollInterval(秒)を設定します。開発サーバーはその間隔で再取得を行い、コンテンツが実際に変更された場合にのみリロードします。作業中に API へアクセスしないようにするには、未設定のままにしてください。
プレビューと同期
リモートコンテンツの取得方法と対象範囲は、2つのフラグで制御します。
--previewをblume devまたはblume buildに付けると、下書きがレンダリングされ、未公開の CMS コンテンツが取得されます。Sanity はpreviewDraftsパースペクティブに切り替わり、Contentful は Preview API を通じて読み込み、Payload と Strapi は下書きをリクエストします。Notion は常にすべてのページを読み込み、Statusが公開済みでないページを下書きとして扱います。そのため、blume devではフラグの有無にかかわらずそれらのページが表示され、blume build --previewではそれらがレンダリングされます。フラグなしの本番ビルドはこれまでどおり下書きを除外するため、プレビュービルドは出荷前に未公開の作業を安全に確認する手段になります。blume syncはすべてのリモートソースを再取得し、ランタイムを再生成します。開発環境はキャッシュ優先で、リモートソースは一度取得されると再起動時には.blume/cacheから提供されます(高速でオフラインにも強い)。そのため、開発サーバーを再起動せずに最新の CMS コンテンツを取得する手段がblume syncです(起動中のサーバーはホットリロードします)。先にキャッシュを破棄するには--forceを追加するか、ソースにpollIntervalを設定して自動更新してください。
blume dev --preview # author workflow: see drafts live
blume build --preview # render a full preview build
blume sync # refresh remote content now
blume sync --force # ...ignoring any cached snapshot
レンダリングとエスケープ
ソースは自身のネイティブな形式(Portable Text、Notion ブロック、リモート HTML)を Markdown/MDX テキストに正規化するため、ページがどこから来たものであっても、同じコンポーネントと Markdown の機能が適用されます。組み込みアダプターはリッチテキストを変換する際にエスケープするため、作成者が CMS で入力したもの({、<b>、import で始まる段落、© など)は書いたとおりにレンダリングされます。リンクは http(s)、mailto:、tel:、および相対パスのリンク先のみが保持され、それ以外のスキーム(javascript:、data:)はリンクのテキストとしてレンダリングされます。また、ソースがダウンロードした SVG 画像はサンドボックス化して提供されます。githubReleases() のリリースノートと mdxRemote() のファイルは、自分で書いたコンテンツと同様に扱われます。その生の HTML は書かれたとおりにレンダリングされるため、信頼できるリポジトリのみを指定してください。