Configuration reference
Use defineDocsConfig() for type inference and immediate validation of unknown
keys:
import { defineDocsConfig } from "@tenphi/cookbook/config";
export default defineDocsConfig({
site: { title: "Example" },
content: { sources: [{ file: "README.md", route: "/" }] },
});Cookbook validates the configuration when it loads. Unknown top-level and section keys are errors.
Start with a complete configuration recipe for common tasks. This page documents the available options; working examples covers repository layouts and shared presets.
For a focused explanation, use content sources, theme basics, fonts and typography, component styles, or publishing metadata. The sections below are the complete configuration reference.
cookbook() and CLI commands discover the same docs.config.ts. Set root
to a directory relative to this file to change where content, local assets,
and the lock live. --root chooses the CLI’s configuration search directory;
--config chooses a config file. An inline integration config object skips
discovery and resolves its root relative to the integration root.
Use mergeDocsConfig(preset, overrides) to compose shared configuration. Objects
merge recursively and arrays replace. Each theme.fonts role replaces its
previous definition, so switching a role from Google to local files takes one
override. Tasty styles preserve default values when adding conditional
overrides. Neither input is mutated. See
working examples.
Map old routes to collected document routes:
redirects: { "/old-guide": "/getting-started" }Pages can also declare aliases: ["/old-guide"] in frontmatter. Page aliases are
relative to the source mount. Cookbook rejects collisions, cycles, and missing
targets, collapses chains, and lets Astro emit static redirects. Internal links
using an alias are rewritten to the canonical route.
site: {
title: "Example Project",
version: "1.2.3",
description: "Documentation for Example Project",
url: "https://docs.example.com",
repository: "https://github.com/example/project",
favicon: "./assets/brand.svg"
}version is the documented package version shown beside the site title. A site
with one locked npm package source infers its version automatically; set this
field for local or multi-package documentation. Read it from the package
manifest when possible so it remains current. url configures Astro’s canonical
site origin and sitemap metadata. If Astro also declares site, the values must
match. It also lets Cookbook put absolute page URLs in llms.txt and a sitemap
pointer in the origin-root robots.txt. repository adds a source link to the
header.
For multiple documentation versions, set site.versions and mount content at
each version root. The header then shows a version selector. It links to the
same route in another version when that page exists and falls back to the
other version’s root when it does not:
site: {
versions: [
{ label: "Latest", routeBase: "/" },
{ label: "v1", routeBase: "/v1" },
],
},
content: {
sources: [
{ file: "README.md", route: "/" },
{ glob: "docs/**/*.md", base: "docs" },
{ file: "versions/v1/README.md", routeBase: "/v1", route: "/" },
{ glob: "versions/v1/docs/**/*.md", base: "versions/v1/docs", routeBase: "/v1" },
],
},Each routeBase must have a home page (a localized home also qualifies), and version roots must be distinct. A
single-version site can continue using site.version for a simple label.
site.logo accepts a local image path, false to hide the mark, or an object
with src (one image) or light and dark (appearance variants). Optional
alt, decorative, href, width, and height control accessible text,
destination, and intrinsic sizing. It applies to the header and mobile drawer.
See the shared logo guide.
The logo and favicon are independent.
Cookbook ships its book mark as the default favicon. Set site.favicon to a
local SVG, PNG, JPEG, WebP, AVIF, or GIF when the documentation should use the
project’s own artwork:
site: {
title: "Example Project",
favicon: {
source: "./assets/brand.svg",
background: "#315efb"
}
}Paths are resolved from the project root. The string shorthand sets only the
source, as in favicon: "./assets/brand.svg". background controls the opaque
canvas used for the Apple touch icon and maskable application icons; it defaults
to Cookbook blue.
At development and build time, Cookbook creates a scalable favicon when the
source is SVG, a 32×32 PNG fallback, a 180×180 Apple touch icon, 192×192 and
512×512 application icons, safe-zone maskable variants, and a web app manifest.
It also emits modern rel="icon", rel="apple-touch-icon", and
rel="manifest" links plus light and dark theme-color metadata. Generated
files live under /_cookbook/icons/, respect Astro’s base, and do not modify
the project’s public/ directory. The maskable variants render the source artwork
at 80% of the canvas on the configured opaque background.
These outputs follow current browser guidance for multiple icon formats and sizes, manifest icon purposes, and the 180×180 Apple touch icon.
Add custom elements to every page’s <head> with the head array. This is the
preferred configuration for analytics scripts and other remote resources:
head: [
{
tag: "script",
attrs: {
defer: true,
src: "https://analytics.example.com/script.js",
"data-website-id": "YOUR-WEBSITE-ID",
},
},
],Each entry accepts a tag, optional string or boolean attrs, and optional
string content. Cookbook renders these entries directly as HTML elements;
they do not pass through Astro’s script or style processing. Use a Head
component override when a local asset needs Astro processing.
Enable source-aware edit links and Git timestamps for the page footer:
editLink: {
baseUrl: "https://github.com/example/project/edit/main/"
},
lastUpdated: true,Cookbook joins editLink.baseUrl with each original repository-relative source
path, not a generated content-collection path. Set editUrl: false or
lastUpdated: false in a page’s frontmatter to opt that page out; a string
editUrl or date-valued lastUpdated overrides the generated value. Package
sources show a timestamp only when their materialized file has Git history or
the page supplies one explicitly.
These settings use Cookbook’s original source paths when constructing links and timestamps.
Cookbook also accepts page presentation frontmatter:
tableOfContents:
minHeadingLevel: 2
maxHeadingLevel: 4
pagefind: true
banner:
content: This API is experimental.
hero:
image:
file: ./assets/product.svg
sidebar:
label: Quick start
order: 1
group: Guides
badge: NEWtemplate: splash uses a wider layout without sidebars by default. Set
tableOfContents in that page’s frontmatter to show its contents list.
Set sidebar: false to omit a page from generated sidebars. label, order,
group, and badge affect both the default sidebar and autogenerated navigation
directories. A badge is plain text and also appears when a navigation item links
to the page, unless that item overrides it. Relative hero images are validated, content-hashed, and copied
with the page’s other local assets. Unrecognized frontmatter is preserved as graph entry metadata, outside the
renderer frontmatter. Use content.frontmatter: "reject" to reject unrelated
fields. Other supported fields include aliases, template, hero, editUrl,
lastUpdated, prev, next, head, draft, and slug.
Set pagefind: false to omit an individual published page from search while
keeping its normal route and navigation. A draft is excluded from search
regardless of pagefind.
Set draft: true to publish a page for review at its normal URL. Drafts remain
available in development and production, and authored links to them are valid.
They are excluded from automatic navigation, pagination, search, sitemaps, and
llms.txt, and receive noindex metadata. Removing draft makes the page
discoverable on the next build. A draft URL is public; this is not access control.
Configure Cookbook’s multilingual routing and language picker:
locales: {
root: { label: "English", lang: "en" },
fr: { label: "Français", lang: "fr" },
ar: { label: "العربية", lang: "ar", dir: "rtl" }
},
defaultLocale: "root",Locale keys other than root are URL prefixes. A source routed to /fr/guide
is the French counterpart of /guide. Navigation and pagination include the
current locale’s published routes. Locale prefixes are added once, after the
site’s deployment base.
Cookbook does not create duplicate fallback pages. When the language picker
cannot find a translation, it links to the equivalent page in defaultLocale,
then an existing locale home or default-language home. The picker labels
cross-language fallbacks. Locales with no usable target are omitted. Header home
links use the same policy, so a missing /fr/ never creates a broken home link.
Alternate-language metadata lists only existing published translations. Drafts
remain directly accessible but are excluded from locale discovery.
content: {
sources: [
{ file: "README.md", route: "/" },
{ glob: "docs/**/*.{md,mdx}", base: "docs" }
],
allowOutsideRoot: false,
localizeRepositoryLinks: false,
frontmatter: "preserve"
}See Content sources for every declaration and its route
rules. Enable localizeRepositoryLinks to turn absolute repository blob,
tree, raw, or Bitbucket src links back into local Cookbook routes when a
matching page was collected. Cookbook uses site.repository for local sources
and each package manifest’s repository metadata for package sources.
Navigation can mix direct routes, nested groups, autogenerated directories, and external links. Groups are recursive and can be nested to any practical depth. Use the object form to add an optional primary tab row above the documentation shell:
navigation: {
tabs: [
{
label: "Guides",
link: "/",
items: [
"/",
{
label: "Build",
items: [
{
label: "Frontend",
items: [
{
label: "Frameworks",
items: ["/react", "/vue"]
}
]
}
]
}
]
},
{
label: "API",
link: "/reference",
items: [
{
label: "Reference",
autogenerate: { directory: "/reference" }
}
]
},
{ label: "Playground", link: "https://example.com/playground" }
],
items: [
"/",
{
label: "Start here",
items: ["/getting-started", "/configuration"]
},
{
label: "Reference",
autogenerate: { directory: "/reference" }
}
]
}Give a group an optional link to use its header as a parent page:
{
label: "Charts",
link: "/charts",
items: [
{
label: "Chart types",
link: "/charts/types",
autogenerate: { directory: "/charts/types" }
}
]
}Group links must name existing root-relative page routes, without the deployment base, a query, or a fragment. The parent page is omitted from its children if it also appears in the manual list or autogenerated directory. It remains in previous/next page navigation. A group with no remaining children becomes a regular page link.
Every navigation object, including manual and autogenerated groups, accepts a
plain-text badge, such as { label: "Offline support", link: "/offline-support", badge: "NEW" }. Links inherit sidebar.badge from their page’s frontmatter;
an explicit badge overrides it, and badge: "" hides it. Badges use brand-derived
accent colors and support partial customization through theme.styles.Sidebar.Badge.
See Sidebar badges for examples.
Top-level sections stay flat; their linked headings navigate to their pages.
For nested groups, clicking an unselected header or its chevron selects the parent
page and opens its children, keeping them open if already expanded. Clicking the
selected parent toggles its children without reloading. Selecting and collapsing
an open, unselected group therefore takes two clicks. Enter and Space work too, while modified clicks and opening a link
in a new tab retain normal link behavior. Groups without a link only toggle.
Only the selected page is highlighted; its ancestors keep their normal styling.
Tabs are omitted when tabs is not set. Give a tab items to replace the
sidebar for that section. Those items also establish section membership, so a
tab can own routes that do not share its URL prefix. A tab stays active for
pages nested below its link; / matches only the home page. When multiple tabs
could match, an exact tab link wins, followed by the longest link prefix and
then sidebar membership. Tabs without items use the top-level items
fallback. Every internal route named anywhere in navigation must exist.
theme: {
brand: {
from: "#2f5bff",
contrast: { apca: [45, 60] }
},
palette: {
surface: { tone: 98, saturation: 0.05 },
text: {
base: "surface",
tone: 0,
saturation: 0,
contrast: { wcag: [7, 10] }
},
heading: {
base: "surface",
tone: [4, 0],
saturation: 0,
contrast: { wcag: [7, 10] }
},
"text-soft": {
base: "surface",
tone: [25, 10],
saturation: 0.05,
contrast: { wcag: [4.5, 7] }
}
},
fonts: {
body: "Inter",
heading: { google: "Newsreader", weights: [400, 700] },
code: {
family: "Project Mono",
files: [{ src: "/fonts/project-mono.woff2", weight: "100 900" }]
}
},
tokens: {
"$radius": "8px",
"$card-radius": "16px",
"$border-width": "1px",
"$layout-width": "87.5rem",
"$content-width": "58rem",
"$sidebar-width": "17.5rem"
},
states: {},
presets: {
body: { boldFontWeight: 680 },
heading: {
fontWeight: 650,
boldFontWeight: 740
}
},
styles: {
ThemeSelect: {
Trigger: { border: "#border-strong" },
Panel: { shadow: "0 1rem 3rem #shadow" }
}
},
contrastLevel: "auto"
}The default brand is okhsl(266 68% 48%), a blue with 68% saturation.
Controls use an 8px radius and cards use 16px. Onest Variable is the default body
and heading family; JetBrains Mono Variable is used for code. theme.fonts loads Google
families by name or local files from public/. See
Fonts and typography for both flows.
The default layout is capped at 87.5rem (1400px), with a 58rem reading
column and a 17.5rem sidebar. brand.from supplies the color seed.
theme.palette supplies semantic Glaze declarations that inherit its hue and
saturation unless a role has its own from. Reading text uses absolute tones:
body text starts at 0 and headings at 4. Glaze applies normal-mode tone
boundaries and adapts the values for dark mode; base and contrast supply
minimum contrast safeguards. palette.heading follows an explicit
palette.text declaration unless configured separately.
Glaze resolves light, dark, and both high-contrast modes independently.
Literal brand color shorthand and structured hue/saturation/tone declarations
remain supported. An APCA floor below 45 requires unsafeContrast: true.
See Theme and components for the color model and
examples.
theme.styles is keyed by Cookbook UI surface name. A plain Tasty style object
contains only the properties to override; Cookbook deep-merges it into that
surface’s complete base object internally. Unknown built-in names and sub-elements are rejected. Register custom
component names and their overrides in theme.customStyles. Structural Astro overrides under
components.overrides remain available when styling alone is insufficient.
theme.states registers additional Tasty state shorthands or replaces a
built-in alias; see the responsive state reference
for all nine defaults. contrastLevel is forwarded to Glaze’s palette
resolution.
The built-in documentation navigation surfaces are available as Sidebar,
TableOfContents, MobileMenuToggle, and MobileNavigationTabs; see
Component styles for their
complete sub-element lists.
markdown: {
stripLeadingBadges: true,
rawHtml: "sanitize",
}stripLeadingBadges removes badge-only paragraphs at the start of a page and
defaults to true. rawHtml accepts "allow", "sanitize", "strip", or "reject".
The default sanitize policy preserves safe elements, including details,
summary, tables, and inline emphasis, while removing executable markup,
event handlers, and presentational attributes. Links and images in sanitized
HTML pass through the content graph. strip removes HTML with a warning,
allow preserves trusted HTML, and reject reports a graph error. Package Markdown in safe mode is
always sanitized even when the global policy is "allow", and package MDX
requires an explicit trust: "mdx" source declaration.
Configure renderer-level Markdown options such as custom remark or rehype
plugins and Shiki languages through Astro’s top-level markdown configuration.
Cookbook preserves those settings while adding its own build-time transforms.
GFM column alignment (:--, :-:, --:) becomes a data-align modifier on
table cells. Restyle it with @own(align=right) and similar states in
theme.styles.MarkdownTable.Cell.
Cookbook preserves custom metadata and supports custom schemas. See extending Cookbook for Astro Markdown plugins, native GitHub alerts, the content query API, and styling limits.
Cookbook renders fenced mermaid blocks as responsive, theme-aware SVG during
the static build. Flowcharts, state, sequence, class, and entity-relationship
diagrams are supported. Invalid or unsupported diagrams remain visible as
source code.
```mermaid
flowchart TD
accTitle: Proposal workflow
accDescr: Evidence is inspected before proposals are decided and applied.
inspect[Inspect evidence] --> seal[Seal proposals]
seal --> decide[Decide eligible items]
decide --> apply[Apply accepted items]
```search: {
enabled: true,
},Search is generated locally with Pagefind during a static build. Disable it for hosts or fixtures that do not need an index. Readers can open the search dialog with Ctrl+K (⌘+K on macOS), type a query, and close it with Escape. Search loads its index when opened, so a development server shows a notice instead of results. Build and preview the site to test actual results. See Search and navigation for the reader experience.
components: {
overrides: {
Header: "./src/components/Header.astro",
Footer: "./src/components/Footer.astro"
}
}Component replacement is the advanced escape hatch. Prefer theme tokens and named styles for visual changes that do not need new structure.
Cookbook uses these Astro component slots. A relative override path resolves from the project root; a package specifier resolves from the app’s dependencies:
| Area | Override names |
|---|---|
| Page shell | Head, PageFrame, Header, Footer, Sidebar, Hero, SiteTitle |
| Navigation and controls | Search, LanguageSelect, ThemeSelect, SocialIcons, MobileMenuToggle, MobileMenuFooter, MobileTableOfContents, TableOfContents, Pagination |
| Content and metadata | MarkdownContent, DraftContentNotice, EditLink, LastUpdated |
An override owns its markup and interaction behavior. Page overrides can read
the validated route and navigation data from Astro.locals.cookbookRoute;
see Extending Cookbook. Use
Custom components for a complete site title example.
Cookbook uses its built-in footer by default, including the “Generated with
Cookbook” credit. Replace the complete footer with the Footer component path
shown above, or remove it with:
components: {
overrides: {
Footer: false,
},
},Disabling the complete footer also removes its edit link, last-updated metadata, and previous/next-page navigation.
build: {
strict: true,
ci: process.env.CI === "true",
cacheDir: "",
maxArtifactBytes: 25 * 1024 * 1024,
maxUnpackedBytes: 100 * 1024 * 1024,
maxFiles: 10_000,
maxPathDepth: 24,
maxAssetBytes: 20 * 1024 * 1024
}strict makes missing internal links errors instead of warnings. ci makes
missing heading fragments errors and defaults to true when CI=true.
Cookbook derives its public base path from Astro’s top-level base setting so
routes and assets cannot drift between two configurations. Page URLs likewise
follow Astro’s trailingSlash and build.format; see
Deployment. An empty cacheDir
uses ~/.cache/cookbook; set an explicit path to relocate downloaded package
artifacts. Package limits protect builds from unexpected registry artifacts;
raise them deliberately for a reviewed package.
Configure the top bar with site.headerLinks. Links appear beside search on
larger screens and in a More popover below 50rem. The desktop header supports
primary buttons; More uses a compact, left-aligned list of uniform navigation
links. Omit the array (or use []) to hide More.
export default defineDocsConfig({
site: {
headerLinks: [
{
label: "Changelog",
link: "https://example.com/changelog",
newTab: true,
},
{ label: "Get started", link: "/getting-started", variant: "primary" },
],
},
});Each entry requires a non-empty label and a link (an HTTP(S) URL,
root-relative route, or fragment). Cookbook prefixes root-relative links with
the Astro base. variant is default or primary and applies on desktop;
newTab defaults to false
and adds safe new-window attributes when enabled. Customize the complete
button and popover style tree through theme.styles.HeaderLinks.
theme.palette.header sets the translucent header’s color declaration. It defaults
to theme.palette.surface; Glaze resolves it for light, dark, and both high
contrast modes. Adjust blur and other header styling via theme.styles.HeaderFrame.
theme.palette.overlay controls the fixed underlay color, defaulting to black at
50% opacity in every scheme. The mobile drawer uses the Glaze shadow token and
a 120ms slide transition; customize these through theme.styles.Sidebar.
Cookbook includes English and French interface messages. Other languages use English for missing messages. Override messages by language code; regional codes fall back to the base language and then English:
translations: {
de: {
appearance: "Darstellung",
closeNavigation: "Navigation schließen",
"navigation.Guide": "Anleitung",
},
},navigation.<configured label> translates named tabs, navigation groups, and
explicitly configured sidebar badges.
Automatically generated links use the title from the translated page.
The supported keys below keep independent overrides, including similar labels:
auto controls contrast, while themeSelect.auto controls color scheme;
search.label labels the search control, while pagefind.search supplies the
search input prompt. No migration or key renaming is needed.
| Keys | Controls or feedback |
|---|---|
copyPage, viewMarkdown, pageCopied, pageCopyError |
Page Markdown actions and copy status. |
draftTitle, draftNotice |
Draft-page notice. |
searchError |
Search loading failure. |
appearance, colorScheme, contrast, normalContrast, highContrast, auto |
Appearance and contrast controls. |
closeNavigation, primary, sections, chooseSection |
Primary and mobile navigation. |
headerLinks, more, closeMore, moreLinks |
Header links and overflow menu. |
versions, documentationVersion, documentationVersions, version |
Version selection and package labels. |
home, generatedWith, viewSource |
Home, footer credit and preview source. |
copyCode, codeCopied, codeCopyError |
Code copy action and status. |
copyHeading, linkCopied, linkCopyError |
Heading link action and status. Preserve {heading} in copyHeading. |
notFound, notFoundDescription, fallback |
Missing-page and language fallback messages. |
sidebarNav.accessibleLabel, menuButton.accessibleLabel |
Sidebar navigation and menu accessible names. |
tableOfContents.onThisPage, languageSelect.accessibleLabel |
Contents heading and language selector. |
themeSelect.light, themeSelect.dark, themeSelect.auto |
Color-scheme options. |
search.label, search.ctrlKey, search.cancelLabel, search.devWarning |
Search control, shortcut, close action and development notice. |
page.nextLink, page.previousLink, page.editLink, page.lastUpdated, page.skipToContent |
Pagination, edit/update labels and skip link. |
pagefind.search, pagefind.clear_search, pagefind.zero_results, pagefind.many_results, pagefind.one_result |
Search input, clearing and result counts. Preserve [COUNT] in count messages. |
Custom component message keys are also preserved. Missing custom keys passed to
Astro.locals.t(key) return the key itself. Changing an override does not alter
other message keys, even when their default text is the same.