This page is auto-generated from public/schema.json. Whenever the schema changes, npm run build:schema-reference regenerates it. Do not edit by hand — your changes will be overwritten on the next build.
nookdocs.config.json lives at the root of your docs repo and controls everything: branding, navigation, themes, API settings, AI features, integrations. Add "$schema": "https://nookdocs.com/schema.json" at the top of your config for IDE autocomplete + inline validation.
{
"$schema": "https://nookdocs.com/schema.json",
"name": "Acme Docs",
"theme": "cedar"
}Top-level keys at a glance
| Key | Type | Required | Summary | |
name | string | ✓ | Project display name (shown in tab title, OG metadata, etc.). | |
theme | enum (10 values) | Built-in theme slug. Affects shell layout + CSS tokens. Legacy aliases still resolve but a | ||
contentRoot | string | Repo folder containing MDX files. Must end with '/'. | ||
appearance | object | Default color scheme behavior. | ||
colors | object | Brand colors + logo. | ||
background | object | Page background colors or CSS gradients. | ||
typography | object | Font family overrides. | ||
navbar | object | Top navigation bar configuration. | ||
legal | object | Legal block — copyright + privacy/terms/cookie links rendered in the site footer. | ||
footer | object | Footer layout + social links. | ||
seo | object | SEO defaults applied to all pages. Per-page frontmatter overrides these. | ||
geo | object | GEO / AEO — generative & answer engine optimization. JSON-LD structured data, AI-crawler c | ||
customCss | string | Per-tenant custom CSS. Appended to the docs site head and cascades over every theme + typo | ||
branding | object | White-labeling controls. Setting branding.poweredBy: false requires the Team plan or highe | ||
advanced | object | Niche behaviors that don't fit elsewhere. | ||
navigation | array | object | Site navigation hierarchy. Either a flat array (V1) or a structured object (V2). | |
api | object | OpenAPI / API reference settings. | ||
brand | object | Pluggable brand asset system (logos, OG images, favicons, manifest). | ||
versions | object[] | Phase 3+ version switcher. Each entry defines a docs version; the navbar shows a dropdown | ||
languages | object[] | Phase 3+ language switcher. Each entry defines a locale; the navbar shows a dropdown to sw | ||
products | object[] | Phase 3+ multi-product switcher. Renders a dropdown near the logo to switch between produc | ||
global | object | Phase 3+ global chrome that persists across product / version / language switches. | ||
redirects | object[] | URL redirects applied at the docs page layer. Tenants add entries to map old paths to new | ||
interaction | object | Navigation interaction toggles. Affects how group/tab clicks behave. | ||
ai | object | AI features (assistant, future agent). | ||
feedback | object | Per-page 'Was this page helpful?' widget at the bottom of every docs page. Default: enable | ||
analytics | object | First-party analytics beacon + dashboard. Records views, searches, feedback, and assistant | ||
contextual | object | Configures the contextual menu shown next to page titles (Copy page, Open in ChatGPT, etc. | ||
sidebar | object | Sidebar appearance overrides. Every key defaults to 'auto', meaning the theme decides — se | ||
codeBlockStyle | enum (4 values) | How fenced code blocks are framed. 'card' is a bordered block with a header strip; 'inset' | ||
layout | object | Where the navigation chrome sits. Each theme picks its own arrangement; these depart from | ||
viewSwitcherStyle | 'auto' / 'dropdown' / 'tabs' | How the page-level View switcher is drawn. 'dropdown' (the default) states the current cho | ||
banner | object | Site-wide announcement banner rendered above the navbar. | ||
search | object | Search UI options. | ||
integrations | object | Third-party analytics / chat integrations. Each provider takes its own small config object | ||
icons | object | Icon rendering options. | ||
metadata | object | Arbitrary key→value metadata attached to the site (exposed to templates and exports). |
name
Project display name (shown in tab title, OG metadata, etc.).
namestringpathrequiredProject display name (shown in tab title, OG metadata, etc.).
theme
Built-in theme slug. Affects shell layout + CSS tokens. Legacy aliases still resolve but are deprecated — maple→larch, classic→cedar, modern→ember, minimal→sage; write the canonical slug.
Deep dive: /configuration/theme
theme'cedar' | 'obsidian' | 'birch' | 'oak' | 'cypress' | 'ember' | 'larch' | 'sage' | 'slate' | 'terminal'pathdefault: larchBuilt-in theme slug. Affects shell layout + CSS tokens. Legacy aliases still resolve but are deprecated — maple→larch, classic→cedar, modern→ember, minimal→sage; write the canonical slug.
contentRoot
Repo folder containing MDX files. Must end with '/'.
Deep dive: /configuration/content-root
contentRootstringpathdefault: docs/Repo folder containing MDX files. Must end with '/'.
appearance
Default color scheme behavior.
Deep dive: /configuration/site-settings#appearance
appearance.default'light' | 'dark' | 'system'pathdefault: systemNo description yet — see the deep-dive page for context.
appearance.strictbooleanpathdefault: falseWhen true, hide the theme toggle (force a single mode).
colors
Brand colors + logo.
Deep dive: /configuration/brand
colors.primarystringpathPrimary accent color (hex). Used for buttons, links, focus rings.
colors.lightstringpathPrimary color in light mode.
colors.darkstringpathPrimary color in dark mode.
colors.logo
Logo images. A root-relative path is served from your repo's public/ folder; an absolute URL is used as given (e.g. a CDN).
colors.logo.lightstringpathLight-mode logo — a path under public/ ("/logo/light.svg") or an absolute URL.
colors.logo.darkstringpathDark-mode logo — a path under public/ ("/logo/dark.svg") or an absolute URL.
colors.logo.hrefstringpathClick target for the logo. Root-relative paths resolve against your docs base, so "/" returns to the docs home even on a subpath. Default: "/".
background
Page background colors or CSS gradients.
Deep dive: /configuration/site-settings
background.lightstringpathLight mode background. Solid hex or any CSS gradient.
background.darkstringpathDark mode background.
typography
Font family overrides.
Deep dive: /configuration/site-settings#typography
typography.fontFamilystringpathDefault sans-serif font family for body text.
typography.headingFontstringpathOverride font for h1-h4 (defaults to fontFamily).
typography.bodyFontstringpathOverride font for paragraph body (defaults to fontFamily).
navbar
Top navigation bar configuration.
Deep dive: /configuration/site-settings#navbar
navbar.links[]
External or internal links shown in the navbar.
navbar.links[].labelstringpathrequiredNo description yet — see the deep-dive page for context.
navbar.links[].hrefstringpathrequiredNo description yet — see the deep-dive page for context.
navbar.primaryCta
Highlighted call-to-action button (e.g. 'Sign up', 'Get started').
navbar.primaryCta.labelstringpathrequiredButton text, e.g. 'Dashboard', 'Sign up'.
navbar.primaryCta.hrefstringpathrequiredWhere it goes. Absolute URL for an external app, or a docs path.
navbar.primaryCta.style'solid' | 'outline' | 'ghost'pathdefault: solidShape. 'solid' = filled pill in the theme accent (default). 'outline' = accent border, transparent fill. 'ghost' = text only.
navbar.primaryCta.colorstringpathFill/border colour. Any CSS colour. Omit to follow the theme's accent — override only when the CTA carries a different brand colour than the docs theme.
navbar.primaryCta.textColorstringpathLabel colour on a solid button. Omit to follow the theme's accent foreground.
navbar.primaryCta.externalbooleanpathOpen in a new tab. Defaults to true for http(s) targets, false for docs paths.
navbar.controls
Where the navbar's controls sit and in what order. Each placement overrides the theme, which otherwise decides all of them together — so you can keep the language switcher in the header while moving the appearance toggle to the sidebar.
navbar.controls.appearance'auto' | 'header' | 'sidebar'pathdefault: autoLight/dark toggle. Where this control sits. 'auto' follows the theme's own preference.
navbar.controls.language'auto' | 'header' | 'sidebar'pathdefault: autoLanguage switcher. Where this control sits. 'auto' follows the theme's own preference.
navbar.controls.version'auto' | 'header' | 'sidebar'pathdefault: autoVersion switcher. Where this control sits. 'auto' follows the theme's own preference. The sidebar slot only exists on themes whose footer renders controls; elsewhere the control won't render at all.
navbar.controls.product'auto' | 'header' | 'sidebar'pathdefault: autoProduct switcher. Where this control sits. 'auto' follows the theme's own preference. The sidebar slot only exists on themes whose footer renders controls; elsewhere the control won't render at all.
navbar.controls.assistant'auto' | 'header' | 'sidebar'pathdefault: autoThe 'Ask AI' button (only when ai.assistant.trigger resolves to 'button'). 'sidebar' gives it a full-width block in the rail; 'header' puts it in the top bar beside the CTA. 'auto' follows the theme.
navbar.controls.order('appearance' | 'language' | 'version' | 'product' | 'assistant')[]pathLeft-to-right order of the controls that end up in the header. Names you leave out keep their default position after the ones listed.
legal
Legal block — copyright + privacy/terms/cookie links rendered in the site footer.
legal.copyrightstringpathCopyright line. The token {year} expands to the current year. Example: '© {year} Acme, Inc.'
legal.privacyUrlstringpathPrivacy policy URL — rendered as a footer legal link.
legal.termsUrlstringpathTerms of service URL.
legal.cookieUrlstringpathCookie policy URL.
legal.links[]
Extra legal links (imprint, accessibility statement, etc.).
legal.links[].labelstringpathrequiredNo description yet — see the deep-dive page for context.
legal.links[].hrefstringpathrequiredNo description yet — see the deep-dive page for context.
footer
Footer layout + social links.
Deep dive: /configuration/site-settings#footer
footer.style'none' | 'page' | 'columns'pathdefault: none'none' hides the footer. 'page' renders a single social-icon + copyright row beneath the page content. 'columns' renders a multi-column link grid with the social row below.
footer.logobooleanpathShow the docs' own logo (colors.logo) in the footer. Reuses the navbar logo — no separate path.
footer.social
Social profile URLs, rendered as brand icons in the page footer. Each key is a platform slug; the value is the profile/page URL.
footer.social.githubstringpathNo description yet — see the deep-dive page for context.
footer.social.xstringpathX / Twitter profile URL
footer.social.linkedinstringpathNo description yet — see the deep-dive page for context.
footer.social.discordstringpathNo description yet — see the deep-dive page for context.
footer.social.youtubestringpathNo description yet — see the deep-dive page for context.
footer.social.facebookstringpathNo description yet — see the deep-dive page for context.
footer.social.websitestringpathNo description yet — see the deep-dive page for context.
footer.social.slackstringpathNo description yet — see the deep-dive page for context.
footer.social.instagramstringpathNo description yet — see the deep-dive page for context.
footer.social.hackernewsstringpathNo description yet — see the deep-dive page for context.
footer.social.mediumstringpathNo description yet — see the deep-dive page for context.
footer.social.telegramstringpathNo description yet — see the deep-dive page for context.
footer.social.blueskystringpathNo description yet — see the deep-dive page for context.
footer.social.threadsstringpathNo description yet — see the deep-dive page for context.
footer.social.redditstringpathNo description yet — see the deep-dive page for context.
footer.social.podcaststringpathNo description yet — see the deep-dive page for context.
footer.links[]
Column definitions for the 'columns' footer style. Each column has a title and an array of links.
footer.links[].titlestringpathNo description yet — see the deep-dive page for context.
footer.links[].itemsobject[]pathNo description yet — see the deep-dive page for context.
footer.width'reading' | 'content' | 'full'pathHow wide the footer's surface runs — independent of footer.style, so it applies to page and columns footers alike. 'reading' (the default) aligns it with the reading column — the same narrow width as the page text and the 'Was this helpful?' feedback block. 'content' widens it to the outer content column (article + TOC width). 'full' spans the whole viewport and the sidebar stops at the footer's top rule. Omit to follow the active theme, then the 'reading' default.
seo
SEO defaults applied to all pages. Per-page frontmatter overrides these.
Deep dive: /configuration/site-settings#seo
seo.titlestringpathDefault site title. Page titles render as '{page} | {title}'.
seo.descriptionstringpathDefault meta description when a page has none.
seo.keywordsstring[]pathDefault meta keywords for the site. Per-page frontmatter 'keywords' overrides.
seo.authorstringpathDefault content author — emitted as <meta name="author">.
seo.ogImagestringpathDefault Open Graph / social preview image URL.
seo.faviconstringpathFavicon URL (path under your repo's public/ folder).
seo.indexing'default' | 'noindex'pathdefault: defaultSet to 'noindex' to hide entire site from search engines.
seo.metatagsobjectpathFree-form <meta> tag map, keyed by meta-name (e.g. 'twitter:site'). Appended to every page.
geo
GEO / AEO — generative & answer engine optimization. JSON-LD structured data, AI-crawler control, and citation signals for AI Overviews / Perplexity / ChatGPT.
geo.structuredDatabooleanpathdefault: trueEmit JSON-LD (TechArticle, BreadcrumbList, Organization, WebSite) on every page.
geo.faqSchemabooleanpathdefault: trueEmit FAQPage JSON-LD from a page's frontmatter faq: [\{ q, a \}].
geo.organization
Publisher entity used in the JSON-LD graph.
geo.organization.namestringpathNo description yet — see the deep-dive page for context.
geo.organization.logostringpathLogo URL (absolute or repo-relative).
geo.organization.sameAsstring[]pathProfile URLs identifying the same entity (X, GitHub, LinkedIn, Wikipedia…).
geo.aiCrawlersanypathAI crawler access in robots.txt. 'allow' (default) or 'block' all AI bots, or a per-bot map keyed by user-agent (GPTBot, ClaudeBot, Google-Extended, PerplexityBot, CCBot, …).
geo.llmsTxt
Extra context lines for the auto-generated /llms.txt.
geo.llmsTxt.introstringpathNo description yet — see the deep-dive page for context.
geo.llmsTxt.contactstringpathNo description yet — see the deep-dive page for context.
geo.topicsstring[]pathPrimary topics/entities the site covers — surfaced as JSON-LD about.
geo.audiencestringpathTarget audience, e.g. 'developers'.
geo.licensestringpathContent reuse / citation license, e.g. 'CC-BY-4.0'.
customCss
Per-tenant custom CSS. Appended to the docs site head and cascades over every theme + typography rule. Pro+ feature — Free tier saves are rejected server-side.
customCssstringpathPer-tenant custom CSS. Appended to the docs site head and cascades over every theme + typography rule. Pro+ feature — Free tier saves are rejected server-side.
branding
White-labeling controls. Setting branding.poweredBy: false requires the Team plan or higher.
branding.poweredBybooleanpathdefault: trueShow the "Powered by NookDocs" attribution in the page footer. Default true. Set to false to hide it (Team+ only).
advanced
Niche behaviors that don't fit elsewhere.
Deep dive: /configuration/site-settings#advanced
advanced.notFound
Custom 404 page configuration.
advanced.notFound.activebooleanpathdefault: falseNo description yet — see the deep-dive page for context.
advanced.notFound.titlestringpathNo description yet — see the deep-dive page for context.
advanced.notFound.descriptionstringpathNo description yet — see the deep-dive page for context.
advanced.drilldownNavigationbooleanpathdefault: falseDeprecated — use interaction.drilldown instead. Read only when interaction.drilldown is absent, so setting both means this one does nothing. Note the defaults differ: this defaulted to false, interaction.drilldown defaults to true.
advanced.showTimestampbooleanpathdefault: trueShow 'Last updated' timestamp at the bottom of each page.
navigation
Site navigation hierarchy. Either a flat array (V1) or a structured object (V2).
Deep dive: /configuration/navigation
navigationanypathSite navigation hierarchy. Either a flat array (V1) or a structured object (V2).
api
OpenAPI / API reference settings.
Deep dive: /configuration/api
api.baseUrlstringpathNo description yet — see the deep-dive page for context.
api.openapistringpathPath to OpenAPI spec (relative to repo root) OR full URL.
api.asyncapistringpathPath or URL to AsyncAPI spec (planned).
api.playgroundanypathdefault: interactiveTry-It playground. "interactive" (or true) runs live requests; "simple" shows the form without sending; "none" (or false) hides it.
api.auth
Default auth scheme for the playground.
api.auth.namestringpathNo description yet — see the deep-dive page for context.
api.auth.type'bearer' | 'basic' | 'apiKey' | 'oauth2'pathNo description yet — see the deep-dive page for context.
brand
Pluggable brand asset system (logos, OG images, favicons, manifest).
Deep dive: /configuration/brand
versions
Phase 3+ version switcher. Each entry defines a docs version; the navbar shows a dropdown to switch between them. Exactly one entry may have default: true.
Deep dive: /content/versioning
versions[].versionstringpathrequiredVersion label, e.g. 'v2', '2024-10'.
versions[].defaultbooleanpathMark as the default version (latest).
versions[].tagstringpathBadge like 'Latest' or 'Deprecated'.
versions[].tabsobject[]pathNo description yet — see the deep-dive page for context.
versions[].groupsobject[]pathNo description yet — see the deep-dive page for context.
versions[].pagesany[]pathNo description yet — see the deep-dive page for context.
versions[].labelstringpathDisplay name shown in the switcher. Falls back to the code/name itself when omitted — set it to show "English" instead of "en".
versions[].slugstringpathURL segment for this entry. Defaults to a slug of the label.
versions[].hiddenbooleanpathKeep the entry out of the switcher while its pages stay reachable.
versions[].status'stable' | 'beta' | 'deprecated' | 'preview'pathStatus badge shown beside the entry.
languages
Phase 3+ language switcher. Each entry defines a locale; the navbar shows a dropdown to switch between them. Exactly one entry may have default: true.
Deep dive: /content/localization
languages[].languagestringpathrequiredISO 639-1 code (en, tr, de, es, fr, ja, zh, ar, etc.).
languages[].defaultbooleanpathNo description yet — see the deep-dive page for context.
languages[].navbarobjectpathTop navigation bar configuration.
languages[].footerobjectpathFooter layout + social links.
languages[].tabsobject[]pathNo description yet — see the deep-dive page for context.
languages[].groupsobject[]pathNo description yet — see the deep-dive page for context.
languages[].pagesany[]pathNo description yet — see the deep-dive page for context.
languages[].labelstringpathDisplay name shown in the switcher. Falls back to the code/name itself when omitted — set it to show "English" instead of "en".
languages[].slugstringpathURL segment for this entry. Defaults to a slug of the label.
languages[].hiddenbooleanpathKeep the entry out of the switcher while its pages stay reachable.
languages[].tagstringpathSmall badge shown beside the entry (e.g. NEW, BETA).
languages[].status'stable' | 'beta' | 'deprecated' | 'preview'pathStatus badge shown beside the entry.
products
Phase 3+ multi-product switcher. Renders a dropdown near the logo to switch between products.
Deep dive: /content/multi-product
products[].productstringpathrequiredNo description yet — see the deep-dive page for context.
products[].iconstringpathNo description yet — see the deep-dive page for context.
products[].descriptionstringpathNo description yet — see the deep-dive page for context.
products[].hrefstringpathNo description yet — see the deep-dive page for context.
products[].tabsobject[]pathNo description yet — see the deep-dive page for context.
products[].groupsobject[]pathNo description yet — see the deep-dive page for context.
products[].pagesany[]pathNo description yet — see the deep-dive page for context.
products[].labelstringpathDisplay name shown in the switcher. Falls back to the code/name itself when omitted — set it to show "English" instead of "en".
products[].slugstringpathURL segment for this entry. Defaults to a slug of the label.
products[].hiddenbooleanpathKeep the entry out of the switcher while its pages stay reachable.
products[].tagstringpathSmall badge shown beside the entry (e.g. NEW, BETA).
products[].status'stable' | 'beta' | 'deprecated' | 'preview'pathStatus badge shown beside the entry.
global
Phase 3+ global chrome that persists across product / version / language switches.
Deep dive: /configuration/navigation#global-chrome
global.anchors[]
global.anchors[].anchorstringpathrequiredLabel shown in the sidebar.
global.anchors[].iconstringpathNo description yet — see the deep-dive page for context.
global.anchors[].iconType'regular' | 'solid' | 'light' | 'thin' | 'sharp-solid' | 'duotone' | 'brands'pathNo description yet — see the deep-dive page for context.
global.anchors[].tagstringpathBadge text like 'NEW'.
global.anchors[].hiddenbooleanpathNo description yet — see the deep-dive page for context.
global.anchors[].hrefstringpathWhere the anchor goes. Absolute URL for an external link, or a root-relative path like "/changelog" for one of your own pages. Mutually exclusive with pages/groups.
global.anchors[].target'_self' | '_blank'pathLink target. Defaults to _blank for external URLs.
global.anchors[].expandedbooleanpathdefault: falseInitial open state when the anchor has children.
global.anchors[].pagesany[]pathNo description yet — see the deep-dive page for context.
global.anchors[].groupsobject[]pathNo description yet — see the deep-dive page for context.
global.dropdowns[]
global.dropdowns[].dropdownstringpathrequiredNo description yet — see the deep-dive page for context.
global.dropdowns[].iconstringpathNo description yet — see the deep-dive page for context.
global.dropdowns[].iconType'regular' | 'solid' | 'light' | 'thin' | 'sharp-solid' | 'duotone' | 'brands'pathNo description yet — see the deep-dive page for context.
global.dropdowns[].tagstringpathNo description yet — see the deep-dive page for context.
global.dropdowns[].hiddenbooleanpathNo description yet — see the deep-dive page for context.
global.dropdowns[].descriptionstringpathNo description yet — see the deep-dive page for context.
global.dropdowns[].expandedbooleanpathdefault: falseInitial open state. Persists in localStorage once the user toggles.
global.dropdowns[].pagesany[]pathNo description yet — see the deep-dive page for context.
global.dropdowns[].groupsobject[]pathNo description yet — see the deep-dive page for context.
global.notFound
global.notFound.pagesany[]pathNo description yet — see the deep-dive page for context.
global.notFound.groupsobject[]pathNo description yet — see the deep-dive page for context.
redirects
URL redirects applied at the docs page layer. Tenants add entries to map old paths to new ones during migrations or rename flows.
Deep dive: /configuration/site-settings#redirects
redirects[].sourcestringpathrequiredSource path. Trailing '/' enables prefix matching; the matched tail is preserved when the destination also ends in '/'.
redirects[].destinationstringpathrequiredDestination path or absolute URL.
redirects[].permanentbooleanpathdefault: falseWhen true, returns HTTP 308 (permanent). Otherwise 307 (temporary). Search engines respect 308 and transfer ranking signals to the new URL.
interaction
Navigation interaction toggles. Affects how group/tab clicks behave.
Deep dive: /configuration/site-settings#interaction
interaction.drilldownbooleanpathdefault: trueControls Group.root click behaviour. When true (default), clicking a group label with root set navigates to that page. When false, clicking only toggles expand/collapse.
ai
AI features (assistant, future agent).
Deep dive: /configuration/ai-assistant
ai.assistant
On-site AI chat widget for your docs — answers from your content.
ai.assistant.enabledbooleanpathdefault: falseShow the assistant on every docs page. Default false (opt-in).
ai.assistant.trigger'button' | 'bar' | 'input'pathHow readers open the assistant. 'button' = a button in the header (after search). 'bar' = a floating pill centered at the bottom of the content. 'input' = a docked input pill in the bottom-right. All open the same conversation drawer. Omit to follow the active theme's own preference (themes that express none fall back to 'button').
ai.assistant.labelstringpathdefault: Ask AIText shown on the trigger (button label / input placeholder) and as the drawer title. Default 'Ask AI'. Override to match your brand voice (e.g. 'Ask Acme', 'Docs AI').
ai.assistant.provider'openai' | 'anthropic' | 'openrouter'pathAI provider for model — only used with Bring-Your-Own-Key. Set it to the provider whose API key you added under AI models (BYOK): openai, anthropic, or your own openrouter account. Without a BYOK key, the assistant uses the AI included in your plan and this field is ignored.
ai.assistant.modelstringpathModel identifier for the chosen provider (e.g. 'gpt-4o' for openai, 'claude-3-5-sonnet-latest' for anthropic, 'anthropic/claude-3.5-sonnet' for openrouter). Only honored when a matching BYOK key is set.
ai.assistant.systemPromptstringpathOverride the default system prompt. Use this to constrain tone, persona, or scope.
feedback
Per-page 'Was this page helpful?' widget at the bottom of every docs page. Default: enabled with Mintlify-style reason options.
Deep dive: /configuration/feedback
feedback.enabledbooleanpathdefault: trueToggle the widget per tenant.
feedback.promptstringpathOverride the top prompt. Default: 'Was this page helpful?'.
feedback.positiveReasons[]
Radio options shown after Yes. Falls back to a sensible default set when omitted.
feedback.positiveReasons[].idstringpathrequiredStable key written to page_feedback.reason.
feedback.positiveReasons[].labelstringpathrequiredShown in the radio list.
feedback.negativeReasons[]
Radio options shown after No.
feedback.negativeReasons[].idstringpathrequiredNo description yet — see the deep-dive page for context.
feedback.negativeReasons[].labelstringpathrequiredNo description yet — see the deep-dive page for context.
feedback.github
GitHub issue automation for negative feedback.
feedback.github.autoIssuebooleanpathdefault: falseOpen a GitHub issue when a thumbs-down includes a comment.
feedback.github.labelsstring[]pathLabels attached to auto-opened issues.
Default: ["docs-feedback"].
analytics
First-party analytics beacon + dashboard. Records views, searches, feedback, and assistant usage into the platform's own tables. Independent of integrations.* (GA4/PostHog/Plausible/...).
Deep dive: /configuration/analytics
analytics.enabledbooleanpathdefault: trueEnable the beacon. Turn off to disable all first-party analytics capture for this tenant.
contextual
Configures the contextual menu shown next to page titles (Copy page, Open in ChatGPT, etc.).
Deep dive: /configuration/contextual
contextual.enabled('content' | 'ai-platforms' | 'mcp' | 'custom')[]pathBuilt-in sections to show. Omit to show all. Unknown values are ignored.
contextual.display'header' | 'toc'pathdefault: headerWhere to render the menu. 'toc' placement is queued for a follow-up release.
contextual.options[]
Tenant-defined custom menu items. Each appears in the 'Custom' section of the dropdown.
contextual.options[].titlestringpathrequiredMenu item label.
contextual.options[].descriptionstringpathSubtitle shown under the title.
contextual.options[].iconstringpathLucide icon name or absolute image URL.
contextual.options[].hrefstringpathrequiredTarget URL. Supports template variables resolved at click time: $page (full URL), $path (pathname), $title (page title), $mdx (URL-encoded MDX source).
contextual.platforms('chatgpt' | 'claude' | 'perplexity' | 'aistudio' | 'grok' | 'windsurf')[]pathWhich AI platforms appear in the 'AI platforms' section. Omit and ChatGPT and Claude are shown — a menu listing seven destinations makes the reader read a list instead of clicking the one they wanted. Name the ones you want to offer to change that. Ignored when 'enabled' leaves 'ai-platforms' out.
sidebar
Sidebar appearance overrides. Every key defaults to 'auto', meaning the theme decides — set one only when you want to depart from the theme you picked.
sidebar.activeStyle'auto' | 'bg-tint' | 'text-only' | 'text-tint' | 'caret'pathdefault: autoHow the current page is marked. 'bg-tint' fills a pill behind it; 'text-only' draws a rail down every row with an accent bar on the active one; 'text-tint' colours the label and paints nothing else; 'caret' puts a chevron in the margin beside the active page and draws no rail. 'auto' follows the theme.
sidebar.showIcons'auto' | 'true' | 'false'pathdefault: autoShow per-page icons in the sidebar. 'auto' follows the theme.
sidebar.scrollbar'auto' | 'always' | 'hover'pathdefault: autoWhether the sidebar scrollbar is always visible or appears on hover. 'auto' follows the theme. Touch devices never show one either way.
sidebar.groupLabelStyle'auto' | 'normal' | 'uppercase' | 'uppercase-mono'pathdefault: autoCasing and weight of group headings. 'auto' follows the theme.
sidebar.collapsibleGroups'auto' | 'true' | 'false'pathdefault: autoWhether sidebar groups get a chevron toggle. 'auto' follows the theme.
sidebar.defaultGroupState'auto' | 'expanded' | 'collapsed'pathdefault: autoHow collapsible groups start: 'expanded' opens all of them, 'collapsed' opens only the group holding the current page. Ignored when groups aren't collapsible. Per-group 'expanded' in navigation still wins.
codeBlockStyle
How fenced code blocks are framed. 'card' is a bordered block with a header strip; 'inset' drops the border for a raised surface with the code recessed in a darker well; 'terminal' keeps sharp corners and a prompt marker before the language. 'auto' follows the theme.
codeBlockStyle'auto' | 'card' | 'inset' | 'terminal'pathdefault: autoHow fenced code blocks are framed. 'card' is a bordered block with a header strip; 'inset' drops the border for a raised surface with the code recessed in a darker well; 'terminal' keeps sharp corners and a prompt marker before the language. 'auto' follows the theme.
layout
Where the navigation chrome sits. Each theme picks its own arrangement; these depart from it without leaving the theme. 'auto' (or omitting a key) keeps the theme's choice.
layout.shell'auto' | 'header-sidebar' | 'sidebar-first' | 'header-only'pathdefault: autoWhich shell frames the page. 'header-sidebar' is a header bar above a sidebar, 'sidebar-first' drops the header so the rail owns the full height, 'header-only' has no rail. The largest of these overrides — it swaps the whole frame.
layout.tabPosition'auto' | 'header' | 'sidebar-list' | 'sidebar-dropdown'pathdefault: autoWhere navigation tabs render — across the header, or down the sidebar as a list or a dropdown.
layout.headerRows'auto' | '0' | '1' | '2'pathdefault: autoHeader rows. '0' drops the header bar entirely, '1' keeps tabs on the logo row, '2' gives them their own strip beneath it.
layout.tabStyle'auto' | 'underline' | 'pill' | 'text' | 'text-right'pathdefault: autoHow header tabs are drawn.
layout.tabAlign'auto' | 'start' | 'center' | 'end'pathdefault: autoHorizontal placement of single-row tabs. Ignored when headerRows is 2.
viewSwitcherStyle
How the page-level View switcher is drawn. 'dropdown' (the default) states the current choice in one line and stays one control however many variants a page offers; 'tabs' spreads them in a row, which reads well for two or three and wraps past that.
viewSwitcherStyle'auto' | 'dropdown' | 'tabs'pathdefault: autoHow the page-level View switcher is drawn. 'dropdown' (the default) states the current choice in one line and stays one control however many variants a page offers; 'tabs' spreads them in a row, which reads well for two or three and wraps past that.
banner
Site-wide announcement banner rendered above the navbar.
banner.contentstringpathrequiredBanner text (inline Markdown supported).
banner.dismissiblebooleanpathLet readers dismiss the banner (remembered per browser).
banner.variant'info' | 'warning' | 'primary'pathVisual tone. Default: info.
search
Search UI options.
search.promptstringpathPlaceholder text shown in the search input.
integrations
Third-party analytics / chat integrations. Each provider takes its own small config object; see the integrations guide for per-provider fields.
integrations.osanoobjectpathosano integration settings.
integrations.intercomobjectpathintercom integration settings.
integrations.frontChatobjectpathfrontChat integration settings.
integrations.ga4objectpathga4 integration settings.
integrations.gtmobjectpathgtm integration settings.
integrations.posthogobjectpathposthog integration settings.
integrations.plausibleobjectpathplausible integration settings.
integrations.fathomobjectpathfathom integration settings.
integrations.mixpanelobjectpathmixpanel integration settings.
integrations.segmentobjectpathsegment integration settings.
integrations.amplitudeobjectpathamplitude integration settings.
integrations.clarityobjectpathclarity integration settings.
integrations.hotjarobjectpathhotjar integration settings.
integrations.logrocketobjectpathlogrocket integration settings.
integrations.pirschobjectpathpirsch integration settings.
integrations.heapobjectpathheap integration settings.
integrations.truestatanypathTrueStat analytics. The site key on its own, or \{ siteKey, domain \} when the docs host differs from the property being tracked.
icons
Icon rendering options.
icons.library'lucide' | 'tabler' | 'fontawesome'pathPreferred library for icon name resolution. Names fall back Lucide → Tabler → Font Awesome. Default: lucide.
metadata
Arbitrary key→value metadata attached to the site (exposed to templates and exports).
Changelog & governance
The canonical schema lives at
public/schema.json. Bumping it requires the 5-layer sync (types + validator + renderer + UI + docs) per AGENTS.md.Run
npm run check:syncto verify a new key is present in all 5 layers before commit.37 top-level keys, 11 shared
$defs.