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

エージェント向けの Markdown

すべてのページの生の Markdown を .md URL または Accept コンテンツネゴシエーションで提供し、独自のコンポーネント用のカスタムシリアライザーを定義でき、読者は Markdown としてコピーとチャットで開くのアクションを追加設定なしで利用できます。

HTML はブラウザーのためのものです。エージェントや LLM は、ページの記述に使われている Markdown のほうがうまく扱えます — トークンが少なく、余計な装飾がなく、コンポーネントもモデルが読める形式でレンダリングされます。Blume は、開発環境でも本番環境でも、設定不要ですべてのページの Markdown を配信します。

生の Markdown

任意のページの URL に .md または .mdx を付けると、その生の Markdown ソースを取得できます — LLM、コーディングエージェント、「Markdown としてコピー」のワークフローに最適です。

URL 返される内容
/quickstart レンダリングされたページ
/quickstart.md コンポーネントが変換されたプレーンな Markdown
/quickstart.mdx コンポーネントが記述されたままの MDX ソース

ネストされたルートも同じように機能し (/content/syntax.md)、ホームページは /index.md で配信されます。

.md バリアントは、JSX を解釈できないコンシューマー向けにコンポーネントをプレーンな Markdown へダウンレベルします。<TypeTable> は Markdown のテーブルに、<Callout> はラベル付きの引用ブロックに、<Steps> は順序付きリストに、<Tabs> は太字ラベルのセクションに、<Card> は本文にリンクとしてタイトルを重ねたものに (そして <CardGroup> はそれが保持するカードに)、<Accordion> は回答の上に太字の質問を置いたものに、<FileTree> はそのリストに、<CodeGroup> はタイトル付きのコードブロックに、<YouTube> はリンクに、そしてその他すべての組み込みコンポーネント — Columns、Frame、Expandable、Badge、Tooltip など — はその読み取り可能なコンテンツになります。型チェッカーを必要とする <AutoTypeTable> は記述されたまま残り、両側をファイルから読み込む <Diff> (src、または before と after) や、owner と repo を指定していない <GithubInfo> も同様です。生成された API リファレンスページを構成するコンポーネントもダウンレベルされます。<Operation> はそのスペック独自の記法によるエンドポイント (GET /pets/{id}、SEND user/signup、query pets) と非推奨マーカー、そして OpenAPI のオペレーションの場合はリクエストボディのプロパティと例、およびレスポンスとその例になり、<ApiTagOperations> はそれらのエンドポイントを各ページへのリンクと概要付きで並べたリストになり、<ApiOverview> は API のバージョンとベース URL になります — これにより、リファレンスページを読むエージェントは何を呼び出せばよいかが分かり、サイト検索でもエンドポイントのパスがマッチします。<Changelog /> は、それがレンダリングするリリース一覧になります。年ごとの見出しの下に、リリースごとのリンク付きの行が並びます。プロパティはリテラルデータとして読み取られ、実行されることはありません — 対象は文字列、数値、真偽値、配列、オブジェクト、テンプレート文字列、そしてページの frontmatter への参照で、title={frontmatter.status} のようなプロパティはレンダリングされたページに表示されるのと同じ値に解決されます。解決されるのはプロパティだけです。Owned by {frontmatter.owner} のようにページ本文中に書かれた式は、Markdown のコピーでは記述されたまま残ります。エージェントにも読ませたい値は本文に直接書くか、すべてのページで同じ値であれば、あらゆる面で置き換えられるコンテンツ変数にしてください。忠実に変換できないもの — カスタムコンポーネントや、関数呼び出しや import から計算されたプロパティ — はそのまま残され、コード内のコンポーネントマークアップには、フェンス付きかインラインかを問わず一切手が加えられません。同じ変換は llms-full.txt と MCP サーバーの get_page ツールにも適用されるため、エージェント向けのあらゆる面がクリーンな Markdown を読み取れます。

MDX そのものが必要な場合は、.mdx バリアントを使用してください。コンポーネントは記述されたまま残り、それ以外の部分は .md バリアントと同様に、URL 経由で読むエージェント向けに整えられます。インクルードは埋め込まれ、<Visibility> はエージェント向けに解決され (for="web" のコンテンツは削除され、for="agents" のコンテンツは残ります)、相対パスの画像とページの隣にある他のファイルへのリンクは配信される URL を指し、相対ページリンクとコンテンツファイルへのルート相対リンク (/guides/setup.md) はそれぞれが指すルートを指します。また、ルート相対リンク (/guides/install) にはサイトの deployment.base と basePath が付加され、翻訳されたページでは、レンダリングされたページのリンクと同じようにそのページのロケールへ移ります。ルート相対パスの画像や public/ 内のファイルへのリンク (/spec.pdf) には deployment.base のみが付加されます。これらのファイルはそこで配信されるためです。

コンテンツネゴシエーション

エージェントが .md の規約を知っている必要はありません。ページ自身の URL に Accept: text/markdown ヘッダーを付けてリクエストすると、同じアドレスで Markdown バリアントが配信され、キャッシュが両者を区別できるよう Vary: Accept が付きます。開発サーバーは標準でこのヘッダーを尊重し、Vercel または Cloudflare のサーバービルドは同じネゴシエーションをデプロイに自動的に組み込みます — Vercel ではルーティングルール、Cloudflare では生成された Worker で — 設定は不要です。ホームページは、コンテンツページではなくカスタムのランディングページであっても、常にネゴシエーションを行います。その Markdown ミラーは llms.txt インデックスにフォールバックするため、サイトのルートに Markdown を要求したエージェントはサイトの機械可読なマップを受け取ります。Markdown のレスポンスには x-markdown-tokens ヘッダーも付きます — Cloudflare の Markdown for Agents の慣例に従った推定トークン数 (1 トークンあたり約 4 文字) で、Blume がレスポンスヘッダーを制御できるすべての面 — 開発サーバー、サーバーレンダリングされたレスポンス、Vercel と Cloudflare でネゴシエーションされたホームページ — に付与されます。その他のデプロイ先はリクエスト時のフックを持たない静的レイヤーからプリレンダリング済みページを配信するため、そこではエージェントが .md URL を直接取得します。エージェント可読性マニフェストは、ヘッダーを尊重するデプロイでのみ contentNegotiation を告知します。

クライアントが Markdown を受け取るのは、Accept ヘッダーに text/markdown (または text/x-markdown。大文字小文字は問いません) が、0 より大きく、かつ text/html 以上の q 値で含まれている場合です。text/markdown と text/markdown, text/html では Markdown が返され、text/html, text/markdown;q=0.9 では HTML が返されます。Vercel のルーティングルールは 2 つの q 値を比較できないため、両方のタイプに 1 未満の q 値が付いている場合 (text/markdown;q=0.9, text/html;q=0.8)、開発サーバーと Cloudflare が Markdown を配信するところで、Vercel は HTML を配信します。どこでも Markdown を受け取るには、q 値を付けずに text/markdown を送信してください。

存在しないページもネゴシエーションします。デフォルトの 404 ページ には、対になる Markdown 版が /404.md にあります — not-found メッセージに続いて、すべてのトップレベルセクション、サイトマップ、llms.txt への復帰リンクが並びます — そして Vercel または Cloudflare のサーバービルドでは、Markdown を優先する存在しない URL へのリクエストは、HTML シェルではなくその本文を実際の 404 ステータスで受け取ります。Vercel では、背後にページがない .md URL も同様です。独自の 404 ページ (pages/404.astro、または /404 のコンテンツページ) を用意すると、デフォルトのページは対になる /404.md とともに置き換えられるため、存在しないページには独自の HTML ページが返されるようになります。

カスタムコンポーネントシリアライザー

agents.markdownComponents — JSX 名からシリアライザーへのマップ — を使って、独自のコンポーネントに Markdown 形式を与えられます。各シリアライザーは、コンポーネントの props (MDX の属性からリテラルデータとして読み取られ、frontmatter への参照は解決済みです)、children (すでに Markdown へダウンレベル済み)、およびページの frontmatter データを受け取り、置き換える内容を返します — JSX をそのまま残す場合は null を返します。

import { defineConfig } from "blume";
import type { ComponentMarkdown } from "blume";

const chart: ComponentMarkdown = ({ props }) =>
  `![${props.title}](/charts/${props.slug}.png)`;

export default defineConfig({
  agents: {
    markdownComponents: {
      Chart: chart,
    },
  },
});

コンテナー系のコンポーネントでは、childComponents("Name") がタグごとに直接の子要素を抽出し — 組み込みの <Steps> シリアライザーが <Step> 項目を集めるのと同じ方法です — childBlocks() はすべての直接の子要素を順序どおりに返します。コンポーネントも散文も同様に、それぞれすでに Markdown のブロックへダウンレベルされています (組み込みの <CardGroup> シリアライザーは、それらのブロックを空行で連結しているだけです)。同名のエントリーは組み込みのシリアライザーを置き換えるため、<Callout> のダウンレベル方法をスタイル変更したり — null を返して完全に対象外にしたりできます。

シリアライザーは components.tsx ではなく blume.config.ts に置きます。設定ファイルはビルド時に実行されるのに対し、コンポーネントファイルは静的に解析されるだけだからです (コンポーネントファイルは .astro ファイルを import することがあり、それらはサイトのビルド外では実行できません)。コンポーネント自体はこれまでどおり components.tsx に登録したままです — markdownComponents は、そのエージェント向けの Markdown 形式を追加するだけです。

Markdown としてコピー

すべてのページには Markdown としてコピー のアクションがあり — 目次の下のページアクションにあります — ページの生の Markdown をクリップボードにコピーします。これは上記の .md URL で配信されるものと同じソースで、LLM、Issue、メモなどにそのまま貼り付けられます。開発環境でも本番環境でも、設定不要ですべてのページで利用できます。

Clipboard API が利用できない場合やブラウザーが拒否した場合 — アプリ内ブラウザー、WebView、安全でないオリジンなど — このアクションはレガシーのコピーコマンドにフォールバックし、クリップボードに何も入らなかった場合は、黙ったままにするのではなくボタンが コピーに失敗しました (actions.copyFailed でローカライズ) と表示します。同じフォールバックが、Blume がレンダリングするすべてのコピーボタンを支えています。

チャットで開く

チャットで開く アクションは、現在のページを AI アシスタント — v0、ChatGPT、Claude、T3 Chat、Scira、Cursor — で開きます。プロンプトにはページの生の Markdown を指すよう事前入力されているため、読んでいる内容についての質問に答えてもらえます。

https://your-site/this-page.md を読んで、このページについて質問できるようにしてください。

Markdown としてコピーと同様、セットアップは不要です。アシスタントは公開 URL 経由でページを取得するため、ページがデプロイされ次第すぐに機能します。

このプロンプトは UI ディクショナリー (actions.openInChatPrompt) の一部なので、ローカライズされたサイトはそれぞれの言語で送信し、i18n.ui で文言を上書きできます — ページの生 Markdown URL に置き換えられる {url} プレースホルダーは残してください。

このアクションを調整するには、ai.openInChat を設定します。false は完全に非表示にし、プロバイダーキーの配列 — "v0"、"chatgpt"、"claude"、"t3"、"scira"、"cursor" — は、列挙した順序でそれらのプロバイダーだけを表示します。

ai: {
  openInChat: ["claude", "chatgpt", "cursor"],
}

ページ全体のアクションではなく、コンテンツ内にコピーしてすぐ使えるプロンプトを埋め込むには、Prompt コンポーネントを使用してください。プロンプトをコピー ボタンと、任意の Cursor で開くリンクを備えたラベル付きの行をレンダリングします。

最終更新

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