Configuration
The single zudoDoc() config reference — every field and its default.
A zudo-doc project is configured through one file: the root zfb.config.ts. It calls zudoDoc() with the fields you want to change; every other setting falls back to a documented default.
import { defineConfig } from "zfb/config";
import { zudoDoc } from "@takazudo/zudo-doc/config";
export default defineConfig(
zudoDoc({
siteName: "My Docs",
// …only the fields you chose; everything has a documented @default.
}),
);zudoDoc() merges your fields over the package defaults per field (you win), supplies the package data defaults (frontmatter schema, directive vocabulary, translations, color schemes, tag vocabulary) unless you override them, and returns a complete ZfbConfig — you spread nothing.
Note
The ZudoDocConfig type is the single source of truth for this reference. Every field carries a @default JSDoc annotation that shows on IDE hover; the tables below mirror those defaults verbatim. When this page and the type disagree, the type wins.
Info
The defaults here are the package defaults a fresh create-zudo-doc project inherits. This showcase enables far more (most features on, i18n, a full header nav) by passing those fields explicitly — do not read the showcase's rich config as the default baseline.
Home page
home
Layout options for the package-owned home page. The default keeps the home content band at the standard no-sidebar width.
Default: { wide: false }
Set wide to true when a larger multi-column category grid benefits from using most of the viewport:
export default defineConfig(
zudoDoc({
siteName: "My Docs",
home: { wide: true },
}),
);The setting applies to both / and locale-prefixed home pages such as /. It works through the package-owned routes, so the scaffolded root route stays the locked one-line re-export:
export { default } from "@takazudo/zudo-doc/routes/index";Type: { wide?: boolean } · Default: { wide: false }
Identity and URLs
siteName
Site name shown in the header and metadata. Page titles render as {page title} | {siteName}. The one field you almost always set.
Default: "Docs"
siteDescription
Site description used in metadata (<meta name="description">, llms.txt).
Default: ""
logo
Home-hero logo. "auto" (the default) renders a generated deterministic SVG seeded by siteName — a framed "decorated plate" mark that adapts to light/dark automatically, so a fresh project gets a presentable hero with no asset work. Set a path string (e.g. "/) to render your own asset as a theme-adaptive CSS mask, or false to hide the logo block entirely.
Run npx zudo-doc eject logo to materialize the generated mark as a real file: it writes public/ and flips this field to "/, so you own an editable asset — tweak it, replace it, or reuse it elsewhere (e.g. for OGP) — instead of the request-time generated default. See Customizing → Rung 5 for the CLI flags.
Default: "auto"
siteUrl
Canonical site origin (e.g. "https:) for sitemap / canonical / og:url. Empty = not set.
Default: ""
base
Public URL sub-path prefix mounted in front of every absolute asset URL (e.g. "/pj/my-site/"). "/" = root-mounted. All internal links (sidebar, nav, prev/next, search) are prefixed automatically.
Default: "/"
Note
Inline markdown links in MDX (e.g. [text](/docs/some-page)) are not rewritten for a non-root base — use relative links in content instead.
trailingSlash
Append a trailing / to extensionless internal hrefs.
Default: false
See Trailing-Slash Policy for how the rule splits between build time and the deployment host.
minifyHtml
Minify production HTML output from zfb build. Set false for readable output while debugging.
Default: true
githubUrl
GitHub repository URL shown in the header (via the github-link header item), or false to omit.
Type: string | false · Default: false
editUrl
"Edit this page" link base, or false to omit. The full URL is editUrl + contentDir + "/" + entryId.
Type: string | false · Default: false
noindex
Add noindex,nofollow to every page (for internal docs).
Default: false
head
Site-wide custom <head> extras (preconnect / preload / stylesheets / meta / alternateLinks). Omit to emit nothing extra.
Type: SiteHeadConfig · Default: undefined
metaTags
<meta> / OpenGraph / Twitter-card emission toggles.
Default: { description: true, keywords: false, ogImage: false, ogSiteName: true, twitterCard: false }
| Property | Type | Description |
|---|---|---|
description | boolean | Emit <meta name="description"> |
keywords | string | false | <meta name="keywords"> value, or omit |
ogImage | string | false | Path for og:image / twitter:image, or omit |
ogSiteName | boolean | Emit og:site_name |
twitterCard | "summary" | "summary_large_image" | false | Twitter Card type, or omit the block |
twitterSite | string (optional) | twitter:site handle |
twitterCreator | string (optional) | twitter:creator handle |
sitemap
Emit a sitemap route.
Default: false
See also the SEO guide for how metaTags and sitemap combine into a complete social-share + search-indexing setup.
onBrokenMarkdownLinks
What to do when a .md/.mdx link cannot be resolved: "warn" logs and continues, "error" fails the build, "ignore" is silent.
Type: "warn" | "error" | "ignore" · Default: "warn"
Color
colorScheme
Active color scheme name (must exist in colorSchemes). The two bundled schemes are Default Light and Default Dark.
Default: "Default Dark"
colorMode
Light/dark mode wiring, or false for a single fixed scheme.
Default: { defaultMode: "dark", lightScheme: "Default Light", darkScheme: "Default Dark", respectPrefersColorScheme: true }
| Property | Type | Description |
|---|---|---|
defaultMode | "light" | "dark" | Initial mode before any user preference |
lightScheme | string | Scheme used in light mode |
darkScheme | string | Scheme used in dark mode |
respectPrefersColorScheme | boolean | Match the OS-level light/dark preference |
colorMode: false, // single fixed scheme (colorScheme only)See the Color reference for the ramp-native model and adding a custom scheme (via the colorSchemes escape hatch below).
Theme packs
Theme packs are installable design bundles layered on top of the color-scheme system above — every pack defines both its light and dark values, so the mode toggle keeps working on any pack. See the Theme Packs reference for the switcher UI, the theme CLI, and pack authoring.
themePack
Active theme pack slug. "default" is the stock zudo-doc look (no pack stylesheet loaded). Must be a member of the resolved themePacks list; an unknown slug fails the build loudly.
Default: "default"
themePackSwitcher
Mount the bottom-right theme-pack switcher flyout (and its browse-all dialog) on every page.
Default: false
themePacks
Enabled pack slugs, in switcher order — the list order is the switcher's Prev/Next cycle order and the browse-all grid order. undefined enables all bundled packs: "default" first, then the rest alphabetically. An explicit list is authoritative — it may omit "default" and reorder freely; duplicates or unknown slugs fail the build loudly.
Default: undefined
themePacks: ["default", "foundry"],Content and i18n
docsDir
Directory (project-root-relative) holding the default-locale docs.
Default: "src/
entryDocSlug
Route slug of the doc page the versions page links to as the "latest docs" entry point (and each past version's docs link). No leading or trailing slashes — e.g. "getting-started" or "overview/getting-started". Not validated at runtime; an invalid slug simply 404s.
Default: "getting-started"
defaultLocale
Default locale code (unprefixed routes).
Default: "en"
locales
Additional locales: code → { label, dir }. Each becomes a / route tree and a docs-<code> collection.
Default: {}
locales: {
ja: { label: "JA", dir: "src/content/docs-ja" },
},defaultLocaleOnlyPrefixes
Route prefixes served only in the default locale (never locale-prefixed). The language switcher omits them on affected pages.
Default: []
See Default-locale-only prefixes.
versions
Docs versions, or false for a single (unversioned) doc set. Each versioned section is served at /.
Type: VersionConfig[] | false · Default: false
| Property | Type | Description |
|---|---|---|
slug | string | Version identifier in the URL path |
label | string | Version-switcher display label |
docsDir | string | Content directory for this version's default-locale docs |
locales | Record (optional) | Per-locale content dirs for this version |
banner | "unmaintained" | "unreleased" | false (optional) | Banner shown on this version's pages |
See the Versioning guide.
mermaid
Enable mermaid diagram rendering in markdown.
Default: true
math
Enable KaTeX math rendering ($…$, $$…$$, fenced math).
Default: false
cjkFriendly
Enable zfb's CJK-friendly line-break / emphasis handling.
Default: false
Tags
tagVocabulary and tagGovernance are orthogonal — one is the runtime gate, the other the enforcement level. The vocabulary entries are supplied separately via the tagVocabularyEntries escape hatch.
docTags
Enable the / + / tag index routes.
Default: false
tagPlacement
Where per-page tags render relative to the content.
Type: "after-title" | "before-pager" · Default: "after-title"
tagGovernance
Tag-governance enforcement level when the vocabulary is consulted ("off" / "warn" / "strict").
Default: "off"
tagVocabulary
Whether the tag vocabulary is consulted at runtime (exact-id recognition and grouped footer). Orthogonal to tagGovernance. This is the boolean gate — the entries themselves come from tagVocabularyEntries.
Default: false
See Tag governance.
Table of contents and headings
tocMinDepth
Minimum heading depth included in the TOC (2–4).
Default: 2
tocMaxDepth
Maximum heading depth included in the TOC (2–4).
Default: 4
Site Settings
designTokenPanel
Enable the interactive Design Token Panel (zdtp) for live editing of spacing, font, size, and color tokens.
Default: false
The panel works with zero extra config. To fully customize it, point designTokenPanelConfigModule at a host module — see Host Chrome Bindings.
sidebarResizer
Enable the draggable sidebar resizer.
Default: false
sidebarToggle
Enable the desktop sidebar collapse toggle.
Default: false
tocToggle
Enable the desktop table-of-contents collapse toggle — a chevron button pinned to the right edge of the viewport on xl screens (1280px and up).
Default: false
Collapsing the TOC hands its width to the content column, so the same page can be read at a wider measure. That is the point of the feature: wide tables and long code lines stop wrapping or scrolling sideways once the TOC is out of the way. The reader's choice is remembered, so it holds across pages and across visits.
The toggle drives the package default TOC only. If you replace the Toc slot through chromeBindingsModule, your own component renders unchanged and no toggle appears — see Host Chrome Bindings.
tocToggle vs. hide_toc
They solve different problems and can be used together. The hide_toc frontmatter is an author decision baked in at build time: the page ships without a TOC, and no reader can bring it back. tocToggle is a reader control: wherever the default TOC is rendered, the reader decides whether to see it right now. It changes nothing on a page that already opted out with hide_toc.
imageEnlarge
Enable click-to-enlarge for content images.
Default: false
findInPage
Mount the FindInPageInit island (Cmd/Ctrl+F find bar) in the body-end islands.
Default: false
Auto-enabled by create-zudo-doc's tauri feature for generated Tauri scaffolds (the generator emits findInPage: true when the tauri feature is selected; it ships with the next create-zudo-doc release). Self-gates on window.__TAURI_INTERNALS__, so it is a safe no-op outside a Tauri shell even when true. A host that overrides the BodyEndIslands chrome-bindings slot (part of ChromeHostBindings — see Host Chrome Bindings for the general seam) must mount the island itself — the package default only applies when the slot is left unset.
dynamicPageTransition
Enable the dynamic (view-transition) page-loading overlay.
Default: false
frontmatterPreview
Frontmatter-preview config (ignore-key overrides), or false to disable the preview panel.
Type: FrontmatterPreviewConfig | false · Default: false
| Property | Type | Description |
|---|---|---|
ignoreKeys | string[] (optional) | Replaces the default ignore list |
extraIgnoreKeys | string[] (optional) | Adds to the defaults (ignored if ignoreKeys is set) |
See the Frontmatter Preview reference.
docHistory
Enable per-page git history (Created/Updated + dropdown). In dev, history is served by @takazudo/zudo-doc-history-server on port 4322; in CI a generator emits static JSON.
Default: false
Note
Fresh scaffolds wire the real scanner-reachable DocHistory island into every generated document-route shape when this feature is selected. No chromeBindingsModule or route edit is required for the history button itself.
See the Document History guide.
docMetainfo
Show the Created/Updated/Author meta block on doc pages (extracted from git history at build).
Default: false
Metadata data requires a host binding
The docHistoryMeta slot defaults to {}. Point chromeBindingsModule at a module that binds it to the build-time history manifest. Fresh route stubs already consume that module; do not edit them. See Custom Components and Host Chrome Bindings.
The binding module must provide docHistoryMeta; with the default {} data slot, there is no metadata block to render. Follow the Document History guide for the paired docHistory setup.
bodyFootUtilArea
Body-foot utility area (doc-history / view-source), or false to disable.
Type: BodyFootUtilAreaConfig | false · Default: false
| Property | Type | Description |
|---|---|---|
docHistory | boolean (optional) | Show the History button (requires docHistory: true) |
viewSourceLink | boolean (optional) | Show a raw-source link (requires githubUrl) |
htmlPreview
Global HTML-preview sandbox config, or undefined to disable global injection into every <HtmlPreview> iframe.
Type: HtmlPreviewConfig | undefined · Default: undefined
| Property | Type | Description |
|---|---|---|
head | string (optional) | Raw HTML injected into <head> |
css | string (optional) | CSS injected as a <style> block |
js | string (optional) | JS injected before </body> |
footer
Footer config (link columns / copyright / taglist), or false for no footer.
Type: FooterConfig | false · Default: false
| Property | Type | Description |
|---|---|---|
links | FooterLinkColumn[] | Link columns |
copyright | string (optional) | Copyright text (HTML allowed) |
Each FooterLinkColumn has title, items ({ label, href }[]), and optional per-locale overrides.
headerNav
Primary header navigation items.
Default: []
| Property | Type | Description |
|---|---|---|
label | string | Display text |
labelKey | string (optional) | i18n translation key (overrides label) |
path | string | Target path |
categoryMatch | string (optional) | Links this tab to a sidebar category |
versioned | boolean (optional) | Whether this item's link carries the active / prefix. Default true — see Header Navigation |
headerNav: [
{ label: "Guides", path: "/docs/guides", categoryMatch: "guides" },
{ label: "Reference", path: "/docs/reference", categoryMatch: "reference" },
],See How to Structure Navigations.
headerRightItems
Header right-hand-side items (toggles, switchers, links), in order.
Default: [{ type: "component", component: "theme-toggle" }]
type | Extra fields | Description |
|---|---|---|
"component" | component — "theme-toggle", "language-switcher", "version-switcher", "github-link", "search" | Built-in header component |
"trigger" | trigger — "design-token-panel", "ai-chat" | Opens a panel (requires the feature) |
"link" | href, label?, ariaLabel?, icon? | Custom link |
"html" | html | Raw HTML |
AI assistant
aiAssistant
Enable the AI-chat assistant route (/, SSR).
Default: false
Running a live assistant requires a deploy adapter, per-IP KV, an Anthropic secret, and the AI_CHAT_DAILY_SPEND_CAP Durable Object migration when the exact cap is enabled — see Customizing → Deploy path and the AI Assistant API. These are host-owned pieces: the package/scaffold supplies a safe placeholder route, not the showcase's live handler, Worker entry, or Durable Object class.
aiChatDemoMode
Short-circuit / with a fixed "disabled" reply (no API key, KV, Durable Object, rate limiter, or provider fetch touched). Set false to enable live Claude-backed chat.
Default: false
aiChatAllowedOrigins
Allowed CORS origins for / when not in demo mode. Empty = block all cross-origin browser requests.
Default: []
aiChatGlobalDailyLimit
Exact Anthropic fetch-admission limit per UTC day across all IPs, or false to skip the exact cap. Provider/network failure does not refund an admitted slot.
Type: number | false · Default: false
Generation and integrations
llmsTxt
Emit an llms.txt route summarising the docs.
Default: false
See llms.txt.
changelogs
Changelog generation config(s), or false to disable.
Default: false
See the Changelog guide.
claudeResources
Claude-resources ingestion config, or false to disable.
Type: { claudeDir; projectRoot?; scanRoot? } | false · Default: false
claudeResources: { claudeDir: ".claude" },See the Claude Resources guide.
Routing seams
packageOwnedRoutes
Build-time package-owned route injection. When true, doc routes are injected from the package (no project-shipped pages/*.tsx layout stubs needed). Set false only if your project ships its own doc-route stubs.
Default: true
chromeBindingsModule
Project-root-relative path to a host module exporting a chromeBindings object built with defineChromeBindings (from @takazudo/; only consumed when packageOwnedRoutes is on). Omit to keep the injected chrome shim at its package-default stubs.
Default: undefined
See Host Chrome Bindings.
Escape-hatch fields
These override non-serializable / data defaults. They travel the import graph rather than being JSON-serialized, so they can carry functions, Zod types, and component maps.
buildDocsSchema
Replace the default docs-frontmatter Zod schema builder entirely. When omitted, zudoDoc() builds the package default (@takazudo/), governance-aware from tagGovernance + tagVocabularyEntries.
Type: () => ZodType · Default: undefined (package default used)
This is how you add custom frontmatter keys — see Customizing → Rung 1.
colorSchemes
Override the color-scheme palette map. When omitted, the two shipped schemes (Default Light / Default Dark) are used.
Type: Record<string, ColorScheme> · Default: undefined
translations
Override the UI-string translation table. When omitted, the shipped en/ja/de defaults are used.
Type: PresetTranslations · Default: undefined
directives
Override the directive → JSX-component-name map. When omitted, the canonical seven are used.
Type: DirectiveVocabulary · Default: undefined
Warning
directives replaces the vocabulary wholesale. Preserve the canonical directives when adding one, or existing :::note, :::warning, and other built-ins stop resolving.
import { defaultDirectiveVocabulary } from "@takazudo/zudo-doc/directive-vocabulary-defaults";
export default defineConfig(
zudoDoc({
directives: {
...defaultDirectiveVocabulary,
callout: "Callout",
},
}),
);See the Directives Registry for the complete component-registration recipe.
tagVocabularyEntries
The tag-vocabulary entries array (distinct from the boolean tagVocabulary gate). Threaded into the route-context virtual module and consulted by the governance-aware default schema builder.
Type: readonly PresetTagVocabularyEntry[] · Default: []
Warning
Do not conflate tagVocabulary (a boolean gate) with tagVocabularyEntries (the entries array). They are separate fields — the gate decides whether the vocabulary is consulted; the entries are what it consults.
Shell passthrough fields
These are host-owned ZfbConfig shell fields, not part of Settings.
port
Dev/preview server port.
Default: 4321
adapter
Deploy-target adapter package name (e.g. "@takazudo/zfb-adapter-cloudflare"). Omit for a pure static build.
Default: undefined (pure static build)
bundle
zfb bundler options (exclude / mainFields / external), passed through verbatim when set.
Default: undefined
An extended project as reference
This showcase's own zfb.config.ts is the canonical "extended project" example — it spreads a typed settings object and passes genuinely showcase-specific data blocks (tag vocabulary, custom translations) through the escape-hatch fields, then adds the shell fields (port, adapter, bundle):
export default defineConfig(
zudoDoc({
...settings,
tagVocabularyEntries: tagVocabulary,
translations,
chromeBindingsModule: "./src/chrome-bindings.tsx",
port: 4321,
adapter: "@takazudo/zfb-adapter-cloudflare",
bundle: { exclude: ["e2e/fixtures/**"] },
}),
);A minimal project needs none of that — just the handful of fields it changes.