zudo-doc のカスタマイズ
最小→拡張のエスカレーションはしご — 1行の設定フィールドから完全なソース制御まで、手を伸ばす順番で。
スキャフォールドされた zudo-doc プロジェクトは意図的に最小限です。1つの設定ファイル、コンテンツ、スタイルシート、そして2つの薄いルートスタブ(インストールを参照)。それ以外のすべて — レイアウト、クローム、スキーマ、トークン — は @takazudo/zudo-doc から出荷され、node_modules から消費されます。
その「唯一の設定ファイル」という理想は、よくあるケースをカバーします。このページは、それでは足りないときのためのエスカレーションはしごです。各段は前の段より侵襲的で、変更が実際に必要とする分だけ登るべきです。段は、実際のプロジェクトがそこに到達しがちな早さで並んでいます。
はしご
| 段 | 手を伸ばすとき | コスト |
|---|---|---|
1. buildDocsSchema の上書き | カスタムの検証付きフロントマターキーが必要 | 関数を1つ置き換え、スキーマを所有する |
| 2. 設定フィールド | 機能のオン/オフや挙動の調整 | なし — ただのフィールド |
| 3. テーマパック | 手作業の調整ではなく、完成された見た目一式が欲しい | なし — フィールド1つか CLI コマンド1つ |
| 4. トークンの上書き | 色・スペーシング・タイポグラフィの再テーマ | global.css の @theme ブロック |
5. zudo-doc eject | 再参照するコンテンツ層コンポーネントを変更する必要 | eject したコピーとそのインポートを所有する |
6. chromeBindingsModule | 主要クロームの置換や、カスタム MDX コンポーネントを含むホストコーラブルの注入 | ホストモジュール1つ |
7. 自前の pages/*.tsx | ルート全体を自分のものにする必要 | そのルートを所有する |
| 8. デプロイ経路 | 本番公開(特に SSR 機能を伴う場合) | アダプター + wrangler.toml + シークレット |
| 9. pre-push / HTML チェックの復元 | ショーケースの検証ゲートを取り戻したい | スクリプトのコピー + 依存追加 |
第1段 — カスタムフロントマターキー(buildDocsSchema)
これは唯一の設定という理想が最初に崩れる場所なので、はしごの先頭に置きます。
他のあらゆる機能は zudoDoc() のフィールドです。フロントマターの検証はそうではありません。ドキュメントコレクションは Zod スキーマで検証されますが、「tier キーも許可する」と伝える設定フィールドは存在しません。スキーマはあなたが置き換える関数 — buildDocsSchema エスケープハッチです。
デフォルトでは zudoDoc() があなたのためにパッケージスキーマを構築します(ガバナンス対応。tagGovernance + tagVocabularyEntries から導出)。独自のキーを追加するには、デフォルトビルダーをインポートし、その結果を拡張して、新しいビルダーを返します:
import { defineConfig } from "zfb/config";
import { zudoDoc } from "@takazudo/zudo-doc/config";
import { buildDocsSchema } from "@takazudo/zudo-doc/docs-schema";
import { z } from "zod";
export default defineConfig(
zudoDoc({
siteName: "My Docs",
// Replace the schema builder entirely. Start from the package default,
// then extend it with your own validated frontmatter keys.
buildDocsSchema: () =>
buildDocsSchema({ tagGovernance: "off" }).extend({
tier: z.enum(["core", "opt-in"]).optional(),
reviewed_by: z.string().optional(),
}),
}),
);これでページは tier: core をフロントマターで宣言でき、ビルド時に検証されます。これを docContentHeaderExtras(第6段)と組み合わせると、そのキーから実際にバッジをレンダリングできます。
Note
buildDocsSchema は ZudoDocConfig の非シリアライズ可能なエスケープハッチフィールドの1つで、colorSchemes、translations、directives、tagVocabularyEntries と並びます。これらはインポートグラフを通じて移動する(JSON シリアライズされない)ため、関数や Zod 型を運べます。設定を参照してください。
第2段 — 設定フィールド
それ以外のほとんどはフィールドです。zudoDoc() はすべての設定をデフォルト化するので、zfb.config.ts には差分だけを並べます:
export default defineConfig(
zudoDoc({
siteName: "My Docs",
docHistory: true,
sidebarToggle: true,
tocToggle: true,
tocMaxDepth: 3,
headerNav: [
{ label: "Guides", path: "/docs/guides", categoryMatch: "guides" },
],
footer: { copyright: "© 2026 Me" },
}),
);手を伸ばすとき: 機能をオン/オフにしたり、挙動(TOC の深さ、ナビゲーション、カラーモード、ロケール)を調整するとき。
限界: 設定フィールドは何が存在し、どう振る舞うかを制御しますが、コンポーネントのピクセルレベルのレンダリングは制御しません。それには第3段〜第5段へ登ります。
デフォルトを含むフィールドの完全な一覧は 設定 リファレンスで、ZudoDocConfig 型自身の JSDoc を反映しています。
第3段 — テーマパック
トークンを手作業で調整し始める前に、同梱のテーマパックが求める見た目をすでに実現していないか確認してください。パックはトークン・フォント・コンポーネントのディテールまで揃った完成済みのデザインバンドルで、設定フィールド1つ、または CLI コマンド1つで適用できます:
zudoDoc({
siteName: "My Docs",
themePack: "foundry",
});pnpm exec zudo-doc theme apply foundryすべてのパックはライト/ダーク両方の値を定義しているため、モードトグルはそのまま機能し続けます。themePackSwitcher: true を加えると、読者が右下のフライアウトからパックをライブで切り替えられるようになります。
手を伸ばすとき: 全体の見た目を変えたくて、同梱パックがそれに合っているとき。
限界: インストール済みパックからそのまま選ぶだけです。パックの上で個々のトークンを調整するのは次の段の仕事です。テーマパックを参照してください。
第4段 — トークンの上書き
スキャフォールドの src/ は短い @import チェーンで、パッケージの theme.css(すべての @theme デザイントークン)、content.css、features.css を取り込み、その後にあなた用の空の @theme { … } ブロックが続きます。これはパッケージのインポートの後に来るため、そこで再定義したものはカスケードで勝ちます:
/* ...package @imports above... */
@theme {
--color-accent: oklch(0.6 0.2 250);
--font-sans: "Inter", system-ui, sans-serif;
--z-index-modal: 200; /* override a single default z-index tier */
}グローバルトークンを読むすべての要素に触れずにコンポーネント単位で再ブランディングするために、パッケージは --zdc-* コンポーネントトークン(見出しフォント、本文フォント、カード角丸、TOC 幅など)も公開しています。:root で一度設定します。
手を伸ばすとき: 変更が再テーマ — 色、スペーシング、タイポグラフィ、角丸 — であるとき。
限界: トークンは再スタイルしますが、マークアップは再構成しません。デザインシステム、Color、コンポーネントトークンを参照してください。
第5段 — コンポーネントのエジェクト
どのトークンでも変更に届かない — マークアップ自体があなたに合わない — 場合は、プロジェクトが再参照するコンテンツ層コンポーネント(たとえば mdxExtras 経由)をエジェクトします。エジェクトはそのソースをパッケージからプロジェクトへコピーし、該当するホストインポートをローカルコピーへ書き換えます:
# eject a component (run via your package manager's bin runner)
pnpm exec zudo-doc eject details
# → copies source into your project and rewrites imports to resolve locally
# see the full list
pnpm exec zudo-doc --helpエジェクト可能な18コンポーネントには、3つの異なる範囲があります:
コンテンツ層:
tab-item、content-admonition、code-group、details。ローカルコピーをレンダリングする必要があるときは、プロジェクト所有の bindings または MDX コンポーネント登録から再参照します。主要クローム:
header、footer、breadcrumb、toc、sidebar、doc-pager。ローカルコピーを対応するchromeBindings.Header、Footer、Breadcrumb、Toc、Sidebar、DocPagerスロットへバインドします。入れ子クローム:
theme-toggle、page-loading、sidebar-tree-island、sidebar-toggle-island、desktop-sidebar-toggle-island、image-enlarge、doc-history、site-tree-nav-island。CLI 警告が示す所有者レベルの binding が必要です。入れ子ファイルをコピーするだけでは、パッケージ所有の親は置き換わりません。
コンテンツ層コンポーネントでは、まずそれをレンダリングするホストコードにローカルインポートを配線してから、ローカルコピーを編集します。mdxExtras に必要な bindings とルートスタブの設定はカスタムコンポーネントガイドにあります。
Note
エジェクトは、どのコンポーネントを所有しているかを記録するプロベナンスを .zudo-doc.json ファイルに書き込みます。このファイルは最初のエジェクト時に遅延生成されます — 新しいスキャフォールドには存在しないため、エジェクトしていないプロジェクトは説明不能な設定ファイルを持ちません。エジェクトを戻すには、まず書き換えられた、または手作業で追加したローカルインポートを元の @takazudo/zudo-doc/... パッケージインポートへ戻します。その後にコンポーネントディレクトリと .zudo-doc.json のエントリを削除します。先にディレクトリを削除すると、それらのインポートが壊れます。
限界: エジェクトしたコピーは、そのコンポーネントのパッケージ更新をもう受け取りません — メンテナンスを引き受けることになります。CLI は各 eject を静的に分類します。主要/入れ子クロームはサポート済み binding が見つかるまで大きく警告し、コンテンツ層は静かな手動 mdxExtras 案内を出します。eject はソースをコピーし、chromeBindingsModule が主要または所有者レベルの置換を実際の描画へ接続するサポート済み継ぎ目です。
別種のエジェクト — zudo-doc eject logo。 このサブコマンドは eject という名前を共有しますが、上記のコンポーネントソースコピーとは異なります — .zudo-doc.json のプロベナンスにもコンポーネントディレクトリにも一切触れません。これはアセットの実体化です — 生成された auto-logo を実ファイルの SVG として描画し、logo 設定フィールドをそれを指すように書き換えます。これにより、リクエスト時に生成されるデフォルトの代わりに、編集可能なファイルを所有することになります。
pnpm exec zudo-doc eject logoこれは public/ を書き出します — マークは内部の SVG luminance マスクとして表現されているため、自前の logo アセットと同じ CSS マスクのヒーロー経路でテーマに追従し続けます — そして zfb.config.ts の logo を "/ に書き換えます。
--seed <name>— マークの描画に使うsiteNameシードを上書きします。zfb.config.tsが正規のスキャフォールド形でない場合(たとえばzudoDoc({ ...settings }))は必須です。この場合シードを静的に読み取れないためです。--force— 既存のpublic/を上書きします。指定しない場合、コマンドを再実行すると、手作業で編集したかもしれないファイルを黙って上書きするのではなくきっぱり拒否します。img/ logo. svg
Note
--seed はシードを与えるだけで、設定の書き換えまで可能にするわけではありません。正規形でない設定の場合、コマンドは SVG は書き出したうえで zfb.config.ts を更新できなかったことを報告し、追加すべき行を表示して非ゼロで終了します。仕上げは手作業で行ってください。
export default zudoDoc({
...settings,
logo: "/img/logo.svg",
});CLI はリテラルで手編集可能なフィールド列だけを書き換えます。そのため、スプレッドで制御されたオブジェクトのどこにフィールドを置くべきかを推測せず、拒否します。
第6段 — chromeBindingsModule(ホストコーラブル)
packageOwnedRoutes: true(デフォルト)では、ドキュメントのクロームがパッケージ内部で組み立てられるため、プロジェクト固有のコンテンツをレンダリングするホストファイルがありません。chromeBindingsModule はそれを取り戻す継ぎ目です。chromeBindings オブジェクトをエクスポートするホストモジュールを指すと、注入ルートがあなたのスロットを拾います — コンテンツヘッダーレンダラー、ホームヒーローの追加要素、カスタムフロントマタープレビューレンダラー、フッタータグローダーなど。
export default defineConfig(
zudoDoc({
siteName: "My Docs",
chromeBindingsModule: "./src/chrome-bindings.tsx",
}),
);import { defineChromeBindings } from "@takazudo/zudo-doc/chrome-bindings";
export const chromeBindings = defineChromeBindings({
docContentHeaderExtras: ({ entry }) =>
entry.data.tier === "core" ? <span class="...">Core</span> : null,
});新しい scaffold のドキュメントルートスタブは、ロケール版と doc-history 版を含め、すでに virtual:zudo-doc-chrome-bindings をインポートして createChrome へ渡します。設定フィールドとモジュールを追加するだけで、ルートスタブを fork する必要はありません。自作ルートでは同じオブジェクトを createChrome(routeCtx, chromeBindings) の第2引数へ渡してください。完全なパターンはカスタムコンポーネントガイドにあります。
Design Token Panel には並行チャネル designTokenPanelConfigModule があります。パッケージデフォルトのパネルはゼロコンフィグ(designTokenPanel: true だけ)で動作し、完全にカスタマイズするには、その設定を buildDesignTokenPanelConfig(mode) をエクスポートするホストモジュールに向けます。両チャネルは — ファイルが無いときの大きな声での失敗挙動も含め — ホストクロームバインディングで詳しく説明されています。
第7段 — 自前の pages/*.tsx
ルート全体を自分のものにする必要があるなら、対応するパスの .tsx ファイルを pages/ に追加します。同じパスに対して、プロジェクト所有のページは常にパッケージ注入ルートに勝ちます — ホストファイルが注入をシャドウします。これが完全にカスタムなランディングルートの追加、特定の注入ドキュメントパスの引き取りの方法です。
scaffold のスタブは特別です。pages/ は何もシャドーしません。/ は注入されないため、これはパッケージホームページを提供する1行の再エクスポートです。pages/docs/[[...slug]].tsx は注入されたドキュメントルートをシャドーしますが、任意のカスタマイズ例ではなく、動作に必要です。注入された動的ルートは現在 zfb dev で404を返すため、このスタブが開発時のドキュメントページを動かし続けます。完全な注入とシャドーイングのモデルはルーティング規約を参照してください。
第8段 — デプロイ経路(明示的な拡張ステップ)
最小スキャフォールドは純粋な静的サイトをビルドします — pnpm build が dist/ を出力し、任意の静的ホストに置けます。設計上、アダプターも wrangler.toml も出荷しません。静的エクスポートを超えることは意図的な拡張ステップです:
デプロイアダプターを追加する。 Cloudflare Workers なら、
adapterシェルフィールドを設定します:zfb.config.tszudoDoc({ siteName: "My Docs", adapter: "@takazudo/zfb-adapter-cloudflare", });アダプターは、プリレンダリングをオプトアウトするルート(
prerender = false)に必須です — これがまさに AI アシスタントのエンドポイントの挙動です。wrangler.tomlを追加する。 Worker 名、カスタムドメインルート、各種バインディングを宣言します。このファイルは新しいスキャフォールドには存在しません — デプロイを決めたときに作成します。AI アシスタントを有効化する場合は配線する。
aiAssistant: trueはpackage-ownedな SSR/seamをマウントします。demo modeでは固定応答を返し、host実装なしでlive modeを選ぶとHTTP 501を返します。package/scaffoldはshowcaseのfull handler、api/ ai- chat worker-entry.ts、AiChatDailySpendCapを出荷しません。本物のClaude対応アシスタントには、まずshowcaseと同等のhost-owned/handlerとsource Worker entry/Durable Objectを実装し、その後に次を行います:api/ ai- chat host handlerを導入した後で
aiChatDemoMode: falseに設定する;RATE_LIMITKV 名前空間を作成し(wrangler kv namespace create RATE_LIMIT)、wrangler.tomlでバインドする;AI_CHAT_DAILY_SPEND_CAPをAiChatDailySpendCapへバインドし、migration tagv1-ai-chat-daily-spend-capとnew_sqlite_classes = ["AiChatDailySpendCap"]を追加する;ANTHROPIC_API_KEYシークレットを追加する(wrangler secret put ANTHROPIC_API_KEY);aiChatAllowedOriginsをサイトのオリジンに設定する。
showcaseのデプロイガイドとAI Assistant APIリファレンスは、host実装の参照として利用してください(シークレット、ソフトなIPごとのKV、UTC日ごとの正確な許可、CORS、プレビュー制約)。class sourceを用意せず名前だけbindingしても動作しません。
第9段 — pre-push と HTML バリデーションの復元
最小スキャフォールドは、ショーケースが実行する検証ゲートを削除しています — 小さなドキュメントセットには重荷だったためです。プロジェクトが成長して取り戻したくなったら、明示的に追加します:
pre-push 検証(
b4push)。 スキャフォールドはscripts/もrun- b4push. sh b4pushの package スクリプトも出荷しなくなりました。before-push スイートを復元するには、自前のスクリプト(format → typecheck → build → link check)を追加し、package.jsonスクリプトとして配線します。ショーケースのscripts/が参照実装です。run- b4push. sh HTML バリデーション。 生成される
package.jsonにはcheck:html/html-validateステップ(および.htmlvalidate.json)が含まれなくなりました。ビルド済み HTML を検証するには、html-validateを dev 依存として追加し、.htmlvalidate.jsonを復元し、dist/に対して実行するcheck:htmlスクリプトを追加します。
Note
gen:z-index / check:z-index のコードジェネレーションも同様に生成プロジェクトから削除されました — 13 のデフォルト z-index ティアは @takazudo/ から無条件に出荷されるため、プロジェクトがカスタムティアセットを保守する場合にのみそのコードジェネレーションを再追加します。単一ティアの上書きは 1 行の @theme 変更(第4段)であり、コードジェネレーションの問題ではありません。
関連ページ
設定 — すべての
zudoDoc()フィールドとそのデフォルトテーマパック — 同梱パック、スイッチャー UI、theme CLI
カスタムコンポーネント — 共有 bindings モジュール経由でプロジェクト所有の MDX コンポーネントを登録する
ホストクロームバインディング —
chromeBindingsModuleとdesignTokenPanelConfigModuleの詳細create-zudo-doc CLI — スキャフォールドが出力するもの