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 }
siteTreeNavIgnore
Top-level category slugs to hide from the package-owned home-page category grid on / and locale-prefixed home pages such as /, and from the <SiteTreeNav /> / <SiteTreeNavDemo /> MDX tags. This does not affect header nav, sidebar, search, or sitemap.
export default defineConfig(
zudoDoc({
siteName: "My Docs",
siteTreeNavIgnore: ["inbox", "develop"],
}),
);The package previously hard-coded ["inbox", "develop"] for this showcase's own need. The package default is now []; set this field when your site needs to hide categories.
Type: string[] · Default: []
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.
logo: "" throws a TypeError at config resolution instead of silently rendering a CSS mask of an empty path — pass false to hide the logo, or omit the field for the default.
Default: "auto"
favicon
The <link rel="icon"> set emitted into every page's <head>. Omit it and you get the four-file convention a fresh create-zudo-doc project ships in public/: favicon.svg, favicon.ico (sizes="any"), favicon-32x32.png, favicon-16x16.png, in that order.
Type: string | FaviconConfig | false · Default: undefined (the four-link set above)
| Value | What it emits |
|---|---|
| omitted | The four-link default |
"auto" | One inline SVG data: URL icon generated from siteName — no asset files needed |
| any other string | One link to that path, with type inferred from the file extension |
a FaviconConfig object | Only the slots you supply, always in svg → ico → png32 → png16 order |
false | No favicon links at all |
"" | Throws a TypeError at config resolution — see below |
The empty string is rejected, not emitted. Per the HTML spec an empty href resolves to the current document, so favicon: "" would silently make every page fetch its own HTML as a "favicon" — a wasted request and a garbage tab icon. zudoDoc({ favicon: "" }) throws a TypeError naming the field instead; pass false for no favicon links, or omit the field for the default four-link set. The same rejection applies to an empty-string FaviconConfig slot (e.g. favicon: { ico: "" }) — the error names the specific slot (favicon.ico). An empty object (favicon: {}, no slots at all) is unaffected and still validly emits nothing. Only the exact empty string is rejected — a whitespace-only value like " " is passed through as-is.
The default is a convention, not a check. It emits all four links whether or not the files exist — so a project whose public/ has no favicon.ico still ships <link rel= on every page, and every visitor's browser console logs a 404 for it. Supplying only the slots you actually have is the fix:
export default defineConfig(
zudoDoc({
siteName: "My Docs",
// No favicon.ico in public/, so no ico link — and no console 404.
favicon: {
svg: "/favicon.svg",
png32: "/favicon-32x32.png",
png16: "/favicon-16x16.png",
},
}),
);FaviconConfig is { svg?: string; png32?: string; png16?: string; ico?: string }. Every key is optional, the order you write them in does not matter (emission order is fixed), and {} emits nothing at all — the same result as false.
A plain string collapses the set to a single link and infers type from the extension: .svg, .png, .ico, .jpg / .jpeg, .gif, .webp, .avif. Anything else omits type and lets the browser sniff. A ?query or #hash suffix is ignored when inferring, so "/ still gets type="image/svg+xml".
favicon: "/icon.png", // one link, type="image/png"
favicon: false, // no favicon links at allfavicon: "auto" needs no asset files at all: it emits one SVG favicon as an inline data: URL, generated deterministically from siteName with the same seeded glyph as logo: "auto", so the hero logo and the browser-tab icon show the same mark. The favicon variant is a square, opaque, fixed light-palette plate — a tab icon cannot follow the page's color mode the way the masked hero logo does.
Note
SVG favicon support is still uneven across browsers (Safari most notably). "auto" degrades to the browser's default blank icon rather than a broken one, but a project that wants maximal coverage should ship real .ico / .png files and use the object form.
Href values starting with / are prefixed with the configured base, so "/ resolves to / on a sub-path deployment. Anything else — an absolute https: URL, a data: URL — is emitted verbatim.
Warning
head.alternateLinks cannot replace this set. Those entries render after the favicon block, so a { rel: "icon" } entry there only appends one more link — it can never remove or override one of these. favicon is the only way to change what the set contains.
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
Set sitemap: true if you want one. At the default false, no / route is emitted at all — the URL 404s. Setting siteUrl is not enough on its own: configuring siteUrl only for canonical / og:url is a perfectly normal setup, so nothing is inferred from it and no build-time warning nudges you. This reference is where that contract lives.
Serving nothing is deliberate. An empty <urlset> at a well-known URL is not a neutral placeholder — it is a positive assertion to crawlers that the site has no indexable URLs, which is worse than the URL simply not existing. The generated robots.txt already drops its Sitemap: line in this state, so the two artifacts now agree instead of contradicting each other. Earlier versions did emit the empty <urlset>; they no longer do.
The gate lives in the package's route injection (packageOwnedRoutes, on by default). A project that hand-wires its own pages/ sits outside it and keeps whatever that page returns — and if that page re-exports the package entrypoint while sitemap is false, the build warns and still writes the empty <urlset>.
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. The map is ordered: the language switcher renders every configured label in that order, so labels are not hard-coded to JP or JA.
Default: {}
locales: {
ja: { label: "JA", dir: "src/content/docs-ja" },
de: { label: "DE", dir: "src/content/docs-de" },
},Locale codes are used as URL segments and directory suffixes. Keep them lowercase and path-safe; duplicate codes, the primary defaultLocale, path separators, and traversal segments are rejected by create-zudo-doc before it writes files. The generated ja tree starts with Japanese prose; other arbitrary locale trees start with English placeholder prose for translation.
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
transclude
Enable :::include{file="…"} transclusion. zudo-doc passes the enabled boolean to zfb as the object-typed markdown.features.transclude: {} setting; configure it here rather than replacing the package-owned Markdown feature block.
export default defineConfig(
zudoDoc({
transclude: true,
}),
);Type: boolean · Default: false
See Transclude for the directive syntax, filesystem restrictions, and build-fatal failure behavior.
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
assetViewer
Generate a default-locale viewer page for every included file under public/<assetViewerDir>/ and enable manifest-backed asset links, cards, code excerpts, and image-caption links in MDX.
Default: false
See Asset Viewer for the directory layout, viewer behavior, and author entry points.
assetViewerDir
Set the directory below public/ that contains viewer-managed files. The same value becomes the raw public URL prefix.
Default: "assets"
The value must be a safe relative URL path and must differ from assetViewerRoutePrefix.
assetViewerRoutePrefix
Set the URL prefix for generated viewer pages.
Default: "files"
With the defaults, public/ is raw at / and has a viewer at /.
assetViewerExclude
Exclude asset-relative glob paths from viewer generation while leaving the underlying files in public/.
Type: string[] · Default: []
For example, ["**/*.map", "drafts/**"] skips source maps and everything below the asset directory's drafts/ folder.
assetViewerIndex
Generate an asset listing page at / when the asset viewer is enabled.
Default: false
See Asset Viewer for the listing behavior and header-navigation setup.
assetViewerIndexing
Independently opt asset viewer pages into the search index, llms.txt, and the sitemap. assetViewer: true is required; indexing subkeys have no effect when the viewer is disabled.
Type: false | { search?: boolean; llmsTxt?: boolean; sitemap?: boolean } · Default: false
Each subkey is off unless it is explicitly true, including when the setting is a partial object. search adds asset pages to search-index.json with asset:-prefixed IDs. llmsTxt adds a ## Files section to llms.txt and appends asset pages to llms-full.txt; text-like assets include up to 8 KB of body text and then an explicit truncation marker, while binary assets are one-line stubs with no body. sitemap adds the / routes.
See Asset Viewer for a configuration example. This showcase enables all three subkeys.
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
For a multi-package project, add one entry per package. Each sourceDir must be the package-specific directory that contains non-index, per-release MDX files—not the top-level changelog landing directory:
changelogs: [
{
sourceDir: "src/content/docs/changelog/core",
outputFile: "packages/core/CHANGELOG.md",
packageName: "@acme/core",
},
{
sourceDir: "src/content/docs/changelog/cli",
outputFile: "packages/cli/CHANGELOG.md",
packageName: "@acme/cli",
},
],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.
codexResources
Codex-resources ingestion config, or false to disable.
Type: { codexDir; projectRoot?; scanRoot? } | false · Default: false
codexResources: { codexDir: ".codex" },See the Codex 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.