プロジェクトで `packageOwnedRoutes: true` を設定すると、`@takazudo/zudo-doc` がドキュメントルートを自前で注入し、プロジェクト側はほぼ空の `pages/` ディレクトリだけを持つことになります。これは便利な反面、通常であればプロジェクト固有のレンダリングを差し込むホストファイルが失われます。**ホストクロームバインディング**はそれを取り戻すための継ぎ目です。型付けされた小さなスロット群（`ChromeHostBindings`）を通じて、コンポーネントをエジェクトすることなく、パッケージ所有のクロームにホスト独自のコンテンツやコーラブルを注入できます。

このページでは、6つの主要クローム置換、名前付きヘッダー右コンポーネント、`docContentHeaderExtras` と `homeExtras` のコンテンツ継ぎ目、そしてすべてのバインディングを注入ルートと自己完結型ルートへ届ける `settings.chromeBindingsModule` を扱います。

[Dynamic content unavailable in text export]

これらの継ぎ目が主に意味を持つのは `packageOwnedRoutes: true` のときです。自前の `pages/*.tsx` スタブを引き続き持つプロジェクトは、レンダリング先のホストファイルをすでに持っており、`createChrome(context, hostBindings)` を直接呼び出せます。パッケージ所有ルートがどのように列挙されるかは[ルーティング規約](https://zudo-doc.takazudomodular.com/ja/docs/develop/routing-conventions#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%83%AB%E3%83%BC%E3%83%88%E3%81%AE%E6%B3%A8%E5%85%A5%E3%81%A8%E3%82%B7%E3%83%A3%E3%83%89%E3%83%BC%E3%82%A4%E3%83%B3%E3%82%B0)を参照してください。



## `ChromeHostBindings` 型

ここで説明する継ぎ目はすべて `ChromeHostBindings` インターフェースのフィールドで、`@takazudo/zudo-doc/factory-context` からエクスポートされています。

```ts
import type { ChromeHostBindings } from "@takazudo/zudo-doc/factory-context";
```

すべてのフィールドは任意です。省略したスロットは、継ぎ目導入前の挙動をバイト単位で再現するパッケージデフォルトにフォールバックするため、部分的なバインディングオブジェクトでも常に安全です。

`ChromeHostBindings` は、クローム自身の呼び出し地点が内部で必要とする広い構造的な形状で各スロットを型付けします。実際の狭い型を持つコンポーネントやコーラブルをそのまま直接代入する — あるいは代入をコンパイル可能にするために `as`／`as unknown as` キャストに頼る — と、本当に重要なチェック、すなわち「渡した値がクロームから渡されるプロパティを実際に受け取れるかどうか」が消えてしまいます。代わりに `@takazudo/zudo-doc/chrome-bindings` からエクスポートされる `defineChromeBindings` でバインディングを組み立ててください。その入力型 `ChromeBindingsInput` は、各スロットの実際の呼び出し地点が渡す正確なプロパティや引数を宣言しているため、クロームが決して渡さないプロパティをコンポーネントが要求している場合はコンパイルエラーになります（#2674 のドリフト検出チェック）。広い `ChromeHostBindings` 形状は、あなたが気にする必要のない内部の単一のワイドニングステップによって生成されます。

## 配信チャネル: `chromeBindingsModule`

`packageOwnedRoutes: true` ではクロームがパッケージ内部で組み立てられるため、バインディングを渡すためのホスト側の呼び出し地点が存在しません。プラグインがルートへ渡すルートコンテキストは**シリアライズ可能なデータのみ**（settings、translations、タグ語彙）を運ぶため、関数やコンポーネントを運ぶことはできません。このチャネルはその制約を回避します。コーラブルそのものをシリアライズするのではなく、それらをエクスポートするモジュールへの**パス**をシリアライズするのです。

`zudoDoc()` 設定の `chromeBindingsModule` に、`defineChromeBindings` で組み立てた名前付き `chromeBindings` エクスポートを持つモジュールを指すプロジェクトルート相対パスを設定します。

```ts title="zfb.config.ts"
import { defineConfig } from "zfb/config";
import { zudoDoc } from "@takazudo/zudo-doc/config";

export default defineConfig(
  zudoDoc({
    // packageOwnedRoutes defaults to true
    chromeBindingsModule: "./src/chrome-bindings.tsx",
  }),
);
```

```tsx title="src/chrome-bindings.tsx"
import { defineChromeBindings } from "@takazudo/zudo-doc/chrome-bindings";

export const chromeBindings = defineChromeBindings({
  // ...seams go here (see below)
});
```

ビルド時にルートプラグインが `chromeBindings` を再エクスポートする仮想モジュールを登録し、注入されたクロームシムがそれをクロームファクトリへスプレッドします。文字列パスはシリアライズ可能なので、「ルートコンテキストはデータのみ」というルールは依然として保たれます — 異なるのはローダーのソースだけです。

[Dynamic content unavailable in text export]

新しい scaffold のドキュメントルートスタブは `virtual:zudo-doc-chrome-bindings` をインポートし、その値を `createChrome` へ渡します。そのため、同じモジュールが自己完結型ルートと注入ルートの両方へ届きます。ルートをゼロから作成する場合も、`createChrome(routeCtx, chromeBindings)` の第2引数として渡してください。[`mdxExtras` のグローバル登録パターン](https://zudo-doc.takazudomodular.com/ja/docs/guides/custom-components#%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E7%99%BB%E9%8C%B2-mdxextras)にルート側の完全な例があります。



## 名前付きヘッダー右コンポーネント

`headerRightItems` はシリアライズ可能なままです。カスタムコンポーネント項目には文字列名だけを置き、呼び出し可能なレンダラーは `chromeBindings.headerRightComponents` で同じ名前へ登録します。完全な設定例は次のとおりです。

```ts title="zfb.config.ts"
import { defineConfig } from "zfb/config";
import { zudoDoc } from "@takazudo/zudo-doc/config";

export default defineConfig(
  zudoDoc({
    siteName: "Acme Docs",
    chromeBindingsModule: "./src/chrome-bindings.tsx",
    headerRightItems: [
      { type: "link", href: "/status", label: "Status" },
      { type: "component", component: "release-badge" },
      { type: "component", component: "search" },
    ],
  }),
);
```

```tsx title="src/chrome-bindings.tsx"
import { defineChromeBindings } from "@takazudo/zudo-doc/chrome-bindings";

export const chromeBindings = defineChromeBindings({
  headerRightComponents: {
    "release-badge": ({ item, index, lang }) => (
      <a
        href={`/${lang ?? "en"}/releases`}
        data-component={item.component}
        data-position={index}
      >
        v4
      </a>
    ),
  },
});
```

レンダラーはシリアライズ済みの `item`、0始まりの `index`、ロケール、GitHub 値、組み込み子スロット、カラーモード／ロケールのゲートを受け取ります。組み込み名（`theme-toggle`、`language-switcher`、`version-switcher`、`github-link`、`search`）は予約済みです。未知の名前や予約名の上書きは、黙って消えるのではなく、設定位置と修正方法を含むエラーになります。

ルートコンテキストを通るのは項目名だけで、`headerRightComponents` 自体はホストのコーラブルモジュールに残ります。ほかの bindings モジュール内コンポーネントと同様、静的なアイランド登録経路も持たない限り SSR 表示用として扱ってください。

### セッション固有の island props を保持する

同一ロケール内でページを移動すると、persist されたヘッダー内の island が持つシリアライズ済み props は、デフォルトでは遷移先ページの値に更新されます。ページから導出する props にはこの動作を使ってください。一方、静的に登録したホスト island がセッション固有の props を持つ場合 — たとえば、初期カウントを次ページの SSR スナップショットで置き換えたくないバッジ — は、island のルート要素か persist されたヘッダー内の祖先要素に `data-zd-props-preserve` を付けます。

```tsx
<div data-zd-props-preserve>
  <SessionBadge initialCount={unreadCount} />
</div>
```

オプトアウトの判定に使われるのは遷移前から存在する live DOM です。遷移先ページだけに属性を付けても、現在の island は保持されません。保持対象の island では `data-props` の更新も remount フラグの付与も行われません。persist されたヘッダー自体に `data-zd-props-preserve` を付けると、配下の全 island が一括でオプトアウトされます。そのため、セッション固有の props を所有する範囲だけを囲むようにしてください。

### 既存スロットの「取り残し」も解消する

`docContentHeaderExtras` と `homeExtras` は新しい継ぎ目ですが、`ChromeHostBindings` にはこのチャネルが存在する以前から、注入ルートへ**届く手段がなかった**スロットがいくつかありました — それらはスタブのデフォルトのまま黙って据え置かれていました。`chromeBindingsModule` はそれらをまとめて解消します。

| スロット | 省略時のデフォルト |
| --- | --- |
| `Header` | パッケージの `HeaderWithDefaults`。`HeaderSlotProps` を受け取る |
| `Footer` | パッケージの `FooterWithDefaults`。`FooterSlotProps` を受け取る |
| `Sidebar` | パッケージの `SidebarWithDefaults`。`SidebarSlotProps` を受け取る |
| `Toc` | パッケージのデスクトップ `Toc`。`TocSlotProps` を受け取る |
| `Breadcrumb` | パッケージの `Breadcrumb`。`BreadcrumbSlotProps` を受け取る |
| `DocPager` | パッケージの `DocPager`。`DocPagerSlotProps` を受け取る |
| `SearchWidget` | サイトの base を内部で束縛したパッケージ検索ウィジェット |
| `headerRightComponents` | `{}` — パッケージ組み込みのヘッダー右名だけを解決する |
| `docHistoryMeta` | `{}` — Created/Updated ブロックなし |
| `sidebarsConfig` | `{}` — 自動生成ツリーのみ |
| `frontmatterRenderers` | `{}` — カスタム[フロントマタープレビュー](https://zudo-doc.takazudomodular.com/ja/docs/reference/frontmatter-preview)レンダラーなし |
| `buildFrontmatterPreviewEntries` | `() => []` — プレビューテーブルが描画されない |
| `loadTagsForLocale` | `() => []` — フッターのタグエントリーなし |
| `tagVocabulary` | `[]` — フッターのタグ語彙なし |
| `BodyEndIslands` | settings から導出されるパッケージのアイランド群 |
| `DocHistory` | 何も描画しない no-op スタブ |
| `DesignTokenPanelBootstrap` | パッケージの固定ターゲットのサーバー境界。ホスト配線なしで `designTokenPanel: true` のときにマウントされる。このスロットは、パッケージのパネルがオンの間に、どのビルダーをマウントするかを差し替えるだけです — ここに何を渡しても `designTokenPanel: false` のままではマウントされません。パッケージのパネルをオフにしたまま自前のパネルをマウントしたい場合は、自前のアイランド（たとえば下の `BodyEndIslands` スロット経由で配線）から `runDesignTokenPanelBootstrapOnce` を呼び出し、`bundleZdtp: true` を設定してください。設定しないと、本物のローダーは例外を投げるスタブのままです。[自前のパネルをマウントする](https://zudo-doc.takazudomodular.com/ja/docs/reference/design-token-panel#%E5%AE%9F%E8%A3%85-%E8%87%AA%E5%89%8D%E3%81%AE%E3%83%91%E3%83%8D%E3%83%AB%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88%E3%81%99%E3%82%8B)を参照してください。 |
| `mdxExtras` | パッケージの SSR コンポーネント（`Details`、`HtmlPreview`、`Island`）と no-op の `PresetGenerator` |
| `docContentHeaderExtras` | 未指定 — 何も描画されない |
| `homeExtras` | 未指定 — 何も描画されない |

つまり、`docContentHeaderExtras` のために作成するモジュールは、たとえば以前はホスト所有ルートでしか機能しなかったカスタムフロントマターレンダラーを登録する場所でもあります。

### `sidebarNodes` は `createHeaderWithDefaults` の prop であり、`Header` バインディングのスロットではない

上表の `Header` 行はコンポーネント全体を置き換えるものです。置き換えたコンポーネントは `HeaderSlotProps` を受け取り、モバイルドロワーのツリーを完全に自前で所有します。`sidebarNodes` はこれとは別の、より狭い継ぎ目です — `HeaderWithDefaultsProps` のオプション prop で、ヘッダーの残りを置き換えずに、*パッケージの*ヘッダーファクトリーが `SidebarToggle` に渡すツリーだけを上書きします。この prop は `createHeaderWithDefaults(ctx)` と `createChrome(...).HeaderWithDefaults` で利用できます。**`HeaderSlotProps` には含まれない**ため、`chromeBindingsModule` で設定した `Header` の置き換えコンポーネントはこの prop を受け取りません。完全な契約は `API.md` の `createHeaderWithDefaults(ctx)` を参照してください。

生成されたドキュメントルートとパッケージ所有ドキュメントルートでは、通常のオブジェクト優先順位に1つだけ意図的な例外があります。`docHistory` が有効な場合、静的にインポートされたパッケージ `DocHistory` を設定済みオブジェクトの後から重ねます。これによりクライアントアイランド登録をスキャナーから到達可能に保ち、ほかのすべての binding は維持されます。仮想ホストモジュール内だけで宣言した `DocHistory` は、これらのルートでは置き換えられません。

[Dynamic content unavailable in text export]

**SSRの表示専用契約のみ**。バインディングモジュールの*内部*で定義したクライアントアイランドは、注入ルートでハイドレートされる保証はありません — 仮想再エクスポートは zfb の静的インポートスキャナーが到達可能なグラフの外側に位置するためです。バインディングモジュールはサーバーレンダリングされるコンテンツとコーラブルに使ってください。注入ルート上でハイドレートするアイランドが必要な場合は、依然として静的にインポートされる登録経路が必要です。



[Dynamic content unavailable in text export]

**ファイル欠落時も空文字列指定時も、挙動は明示的**。`chromeBindingsModule` が設定されているのに解決先のファイルが存在しない場合、ビルドはプラグインのセットアップ時に、解決された絶対パスを示すエラーで失敗します — 黙って空にフォールバックすることはありません。`chromeBindingsModule` に空文字列や空白のみの文字列が設定されている場合も、ビルドはプラグインのセットアップ時に、設定名を示すエラーで失敗します。設定自体が省略されている場合（未設定の場合）、チャネルは `export const chromeBindings = {}` を出力し、設定を省略した場合とバイト単位で同一の挙動になります。



## `docContentHeaderExtras` — コンテンツヘッダーへの注入

`docContentHeaderExtras` は、ドキュメントのコンテンツヘッダー内、**ページの `<h1>` とメタ情報ブロックの間**に追加コンテンツを描画します。これはページエントリを受け取ってレンダリング可能な出力を返す*レンダラー*であり、プロパティから再導出するのではなく、現在のページのフロントマターを自然にキーとして扱えます。

```ts
docContentHeaderExtras?: (args: {
  entry: DocPageEntry;
  slug: string;
  locale: string;
  isFallback?: boolean;
  version?: string;
}) => unknown;
```

よくある用途は、カスタムフロントマターフィールドから導出するティアバッジです。フロントマターで `tier: core` または `tier: opt-in` を宣言するページに対して次のように書けます。

```tsx title="src/chrome-bindings.tsx"
import { defineChromeBindings } from "@takazudo/zudo-doc/chrome-bindings";

export const chromeBindings = defineChromeBindings({
  docContentHeaderExtras: ({ entry }) => {
    const tier = entry.data.tier;
    if (tier !== "core" && tier !== "opt-in") return null;
    const label = tier === "core" ? "Core" : "Opt-in";
    const tone = tier === "core" ? "bg-accent text-bg" : "bg-surface text-fg";
    return (
      <span
        class={`inline-block px-hsp-sm py-vsp-2xs text-caption rounded-full ${tone}`}
      >
        {label}
      </span>
    );
  },
});
```

デフォルト: 未設定 → 何も描画されず、ヘッダー出力は継ぎ目導入前のヘッダーとバイト単位で同一になります。

[Dynamic content unavailable in text export]

このレンダラーは4つのドキュメントルートすべてで `entry` ドキュメントページに対して呼び出され、**バージョン付きページも含みます**。バージョン付きページでは `version` 引数を受け取ります。バージョン付きページではメタ情報ブロックとタグは非表示になります — そこで描画するかどうか、どう描画するかはレンダラー自身が判断します。バージョン付きルートのモデルについては[バージョニング](https://zudo-doc.takazudomodular.com/ja/docs/guides/versioning)を参照してください。



## `homeExtras` と `HomePageView` — ホームヒーローへの注入

`homeExtras` は、ホームヒーローのリンク行の末尾に、直前の要素（プライマリリンクや GitHub リンク）と `/` 区切りで、追加コンテンツをインラインで描画します — 例えば overview/GitHub のリンクと並べてブランドやソーシャルのリンクを置く用途です。

段落、リスト、長い紹介文には [home.introMarkdown](https://zudo-doc.takazudomodular.com/ja/docs/guides/configuration#%E3%83%9B%E3%83%BC%E3%83%A0%E3%83%9A%E3%83%BC%E3%82%B8-home) を使います。サイトの識別情報の下に独立したコンパクトな文章領域を表示し、`homeExtras` と `extras` は引き続きインラインのナビゲーション追加に使います。

```ts
homeExtras?: (args: { locale: string }) => unknown;
```

```tsx title="src/chrome-bindings.tsx"
import { defineChromeBindings } from "@takazudo/zudo-doc/chrome-bindings";

export const chromeBindings = defineChromeBindings({
  homeExtras: ({ locale }) => (
    <a
      href="https://example.com/blog"
      class="text-fg underline hover:text-accent"
    >
      Read the blog
    </a>
  ),
});
```

### 優先順位: `extras` プロパティが勝つ

共有のホーム本体は `HomePageView` が組み立て、パッケージルートとホストページのどちらもこれを呼び出します。`HomePageView` は `extras` プロパティ — ホストページが直接渡す描画済みの値 — を受け取ります。両方が存在する場合は**プロパティが勝ちます**。

```tsx
// resolved inside HomePageView as:
extras ?? hostBindings.homeExtras?.({ locale })
```

この非対称性は意図的なものです。ホストページは手元に JSX（値）を持っている一方、注入/バインディング経路はレンダリング時に `locale` 文字列しか持たず、そこから自前でコンテンツを導出しなければなりません（レンダラー）。

### `/` ルートのトポロジー

`/` にあるデフォルトホームは、ルートプラグインによって**決して注入されません** — zfb が `/` パターンを拒否するためです（アップストリーム [Takazudo/zudo-front-builder#1227](https://github.com/Takazudo/zudo-front-builder/issues/1227)）。scaffold の `pages/index.tsx` は `@takazudo/zudo-doc/routes/index` を再エクスポートする1行のファイルで、`extras` プロパティは渡しません。使用する注入済み `/` ルートが存在しないため、`/` では常にホストファイルが優先されます。

- 変更していない **`/` ホーム**はパッケージルートの再エクスポートを使い、`extras` プロパティ経由で `homeExtras` を受け取りません。
- **注入された `/[locale]` ホーム**は `chromeBindingsModule` を通じて `hostBindings.homeExtras` を読み取ります。

ルートホームをカスタマイズするには、再エクスポートを `HomePageView` を呼び出して `extras` を渡す自前のページに置き換えます。i18n サイトでは、その値とロケールホーム用の `homeExtras` が返す値を同じ内容にしてください。

## Design Token Panel チャネル（`designTokenPanelConfigModule`）

Design Token Panel には独自のホストモジュールチャネルがあり、**`chromeBindingsModule` とまったく同じ仕組み**で動作します — 同じメカニクス、同じ「ファイルが無ければ大きな声で失敗する」挙動 — ただしクロームバインディングの代わりにパネルの設定ビルダーを運びます。

パネルは動作にホスト設定ファイルを**必要としません**。`designTokenPanel: true` にすると、注入された `DesignTokenPanelBootstrap` アイランドは、出荷済みのトークンマニフェストとバンドルされた Default Light / Default Dark スキームから導出された**パッケージデフォルトのビルダー**（`@takazudo/zudo-doc/design-token-panel-config`）を使います。これがゼロコンフィグの経路です。

パネルを完全にカスタマイズするには、`designTokenPanelConfigModule` に、名前付きの `buildDesignTokenPanelConfig(mode)` をエクスポートするホストモジュールを指すプロジェクトルート相対パスを設定します:

```ts title="src/design-token-panel-config.ts"
import type { PanelConfig } from "@takazudo/zdtp";

type PanelMode = "light" | "dark";

export function buildDesignTokenPanelConfig(mode: PanelMode): PanelConfig {
  // return a mode-scoped panel config (spacing/font/size/color tiers)
  // ...
}
```

ルートプラグインは3番目の仮想モジュール（`virtual:zudo-doc-design-token-panel-config`）を登録し、あなたのビルダーを re-export します。`chromeBindingsModule` と同様、設定を通じて移動するのは**パス**だけで、ビルダー自体はモジュールグラフ経由でインポートされます。

[Dynamic content unavailable in text export]

`designTokenPanelConfigModule` は `chromeBindingsModule` と同様、`ZudoDocConfig` の第一級フィールドです — インラインの `zudoDoc({ … })` キーとしてそのまま渡せます。パネルの有効化（`designTokenPanel: true`）は従来どおりインラインで動作します。



`chromeBindingsModule` との違いで知っておくべき点があります:

- **デフォルトは空オブジェクトではなくパッケージビルダーです。** 設定が無い場合、ローダーはパッケージデフォルト（完全に動作するパネル）を re-export します — フォールバックすべき意味のある「空の」ビルダーは存在しません。
- **スキャナー到達可能性がこのコントラクトの一部です。** 各サーバー境界はクライアントのターゲットを静的にインポートします。パッケージデフォルトとルート専用の設定済み境界は、それぞれ別の固定ターゲットを持ち、設定済みクライアントは設定仮想モジュール経由でビルダーをインポートします。ホストの差し替えも、バインディングマップに生のクライアントターゲットを渡すのではなく、以下の境界合成規則に従います。
- **この設定がある間、自己完結型の `pages/` スタブはパネルをマウントしません。** この設定はパッケージ注入ルートでレンダリングされるページにしか届かず、パネルの設定はブラウザセッションごとに一度だけ行われます — そのため、パッケージデフォルトのブートストラップをマウントするスタブページがハードロードの入口になると、セッション全体の設定をそのページが決めてしまっていました。設定が存在する場合（かつ明示的な `chromeBindings.DesignTokenPanelBootstrap` が無い場合）、スタブでレンダリングされるページはパネルアイランド（およびヘッダーのパネルボタン）を一切マウントしません。注入ルートはどの入口ページからでも、あなたの設定済みパネルを受け取ります。スタブページにもパネルを出したい場合は、クライアントのブートストラップを以下のサーバー境界経由で渡してください — このバインディングはどこでも優先されます。

同じガード規則が適用されます: 明示的な空文字列、存在しないファイル、ディレクトリパスは、プラグインのセットアップ時に解決済みパスを明示して大きな声で失敗します。`storagePrefix: "zudo-doc-tweak"` はパッケージデフォルトで維持されるため、既存のユーザー保存は引き継がれます。

## DocHistory の境界

`DocHistory` スロットもサーバー境界を受け取ります。パッケージのクライアントを使う場合は、`@takazudo/zudo-doc/doc-history-area` から `DocHistoryBoundary` をインポートし、`DocHistory` として登録してください。この境界は任意の `ssrFallback` 子要素をサーバー側で処理し、固定クライアントターゲットを `when="idle"` の Island と Fragment で包みます。カスタム境界でも `ssrFallback` を取り除いてから、残りのシリアライズ可能な props をクライアントへ渡してください。フォールバックの JSX をクライアントデータとして転送してはいけません。領域を描画するかどうかは、既存のドキュメント履歴の設定と除外ゲートが引き続き制御します。

## パネル境界の差し替え

v6 の `chromeBindings.DesignTokenPanelBootstrap` は、生の `"use client"` コンポーネントではなく、props を受け取らない**サーバー境界**を受け取ります。クライアントのブートストラップを静的にインポートし、固定ターゲットの `Island` を Fragment で包んで返します。このサーバーファイルはクライアントモジュールと分けてください。クライアントのブートストラップでは、[自前のパネルをマウントする](https://zudo-doc.takazudomodular.com/ja/docs/reference/design-token-panel#%E5%AE%9F%E8%A3%85-%E8%87%AA%E5%89%8D%E3%81%AE%E3%83%91%E3%83%8D%E3%83%AB%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88%E3%81%99%E3%82%8B)の例のように、`getScope().onActivate` 内で `runDesignTokenPanelBootstrapOnce` を起動します。

```tsx title="src/panel-boundary.tsx"
/** @jsxRuntime automatic */
import { Island } from "@takazudo/zfb";
import { HostPanelBootstrap } from "./host-panel-bootstrap";

export function HostPanelBoundary() {
  return <>{Island({ when: "load", children: <HostPanelBootstrap /> })}</>;
}
```

```tsx title="src/chrome-bindings.tsx"
import { defineChromeBindings } from "@takazudo/zudo-doc/chrome-bindings";
import { HostPanelBoundary } from "./panel-boundary";

export const chromeBindings = defineChromeBindings({
  DesignTokenPanelBootstrap: HostPanelBoundary,
});
```

この差し替えスロットでは `designTokenPanel: true` を維持します。設定のゲートとハイドレーション前のトグル shim は引き続きパッケージが管理し、機能を無効にすると境界も shim も出力しません。明示的なホスト境界は、`designTokenPanelConfigModule` がパッケージデフォルトを抑制する場合も優先され、注入ルートの設定済みデフォルトよりも優先されます。パッケージ機能を無効にして独立したホストパネルをマウントする場合は、リンク先の独立した `BodyEndIslands` 経路を使ってください。

`createBodyEndIslands` を直接使う場合も、任意の依存コンポーネント `DesignTokenPanelBootstrap` と `ThemePackSwitcher` は同じ合成規則に従います。渡すコンポーネント側が固定ターゲットの Fragment で包んだ境界を所有し、ファクトリーは機能のゲート内で描画するだけです。依存コンポーネントを省略した場合、そのアイランドは従来どおり何も描画しません。クライアント関数をアイランドの props として渡すことはありません。

## 関連ページ

- [zudo-docのカスタマイズ](https://zudo-doc.takazudomodular.com/ja/docs/reference/customizing) — 最小→拡張のはしご。`chromeBindingsModule` はその6段目
- [フロントマタープレビュー](https://zudo-doc.takazudomodular.com/ja/docs/reference/frontmatter-preview) — このチャネルが取り残しを解消する `frontmatterRenderers` スロット
- [設定](https://zudo-doc.takazudomodular.com/ja/docs/guides/configuration) — `zudoDoc()` の完全なフィールドリファレンス
- [Design Token Panel](https://zudo-doc.takazudomodular.com/ja/docs/reference/design-token-panel) — このチャネルが設定するパネル UI