@tenphi/cookbook 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +8 -0
  2. package/docs/architecture.md +91 -0
  3. package/docs/authoring.mdx +86 -0
  4. package/docs/cli.md +88 -0
  5. package/docs/configuration.md +518 -0
  6. package/docs/content-sources.md +150 -0
  7. package/docs/customization-rules.md +153 -0
  8. package/docs/deployment.md +78 -0
  9. package/docs/examples.md +95 -0
  10. package/docs/getting-started.md +124 -0
  11. package/docs/index.md +74 -0
  12. package/docs/migration.md +36 -0
  13. package/docs/starlight-comparison.md +124 -0
  14. package/docs/theme-and-components.md +668 -0
  15. package/docs/upstream/glaze/LICENSE +21 -0
  16. package/docs/upstream/glaze/README.md +156 -0
  17. package/docs/upstream/glaze/docs/api.md +2021 -0
  18. package/docs/upstream/glaze/docs/methodology.md +686 -0
  19. package/docs/upstream/glaze/docs/migration.md +351 -0
  20. package/docs/upstream/glaze/docs/okhst.md +207 -0
  21. package/docs/upstream/manifest.json +18 -0
  22. package/docs/upstream/tasty/LICENSE +21 -0
  23. package/docs/upstream/tasty/README.md +685 -0
  24. package/docs/upstream/tasty/docs/README.md +39 -0
  25. package/docs/upstream/tasty/docs/adoption.md +323 -0
  26. package/docs/upstream/tasty/docs/ai-agents.md +229 -0
  27. package/docs/upstream/tasty/docs/comparison.md +448 -0
  28. package/docs/upstream/tasty/docs/configuration.md +823 -0
  29. package/docs/upstream/tasty/docs/debug.md +335 -0
  30. package/docs/upstream/tasty/docs/design-system.md +455 -0
  31. package/docs/upstream/tasty/docs/dsl.md +1021 -0
  32. package/docs/upstream/tasty/docs/getting-started.md +238 -0
  33. package/docs/upstream/tasty/docs/injector.md +634 -0
  34. package/docs/upstream/tasty/docs/methodology.md +648 -0
  35. package/docs/upstream/tasty/docs/migration-v3.md +285 -0
  36. package/docs/upstream/tasty/docs/pipeline.md +749 -0
  37. package/docs/upstream/tasty/docs/plugins.md +353 -0
  38. package/docs/upstream/tasty/docs/react-api.md +681 -0
  39. package/docs/upstream/tasty/docs/runtime-benchmarks.md +351 -0
  40. package/docs/upstream/tasty/docs/ssr.md +610 -0
  41. package/docs/upstream/tasty/docs/styles.md +677 -0
  42. package/docs/upstream/tasty/docs/tasty-static.md +582 -0
  43. package/package.json +11 -6
@@ -0,0 +1,518 @@
1
+ ---
2
+ title: Configuration reference
3
+ description: Configure site metadata, head elements, content, navigation, Markdown, search, theme, and build validation.
4
+ sidebar:
5
+ order: 4
6
+ ---
7
+
8
+ Use `defineDocsConfig()` for type inference and immediate validation of unknown
9
+ keys:
10
+
11
+ ```ts
12
+ import { defineDocsConfig } from "@tenphi/cookbook/config";
13
+
14
+ export default defineDocsConfig({
15
+ site: { title: "Example" },
16
+ content: { sources: [{ file: "README.md", route: "/" }] },
17
+ });
18
+ ```
19
+
20
+ Cookbook validates the configuration when it loads. Unknown top-level and
21
+ section keys are errors.
22
+
23
+ ## Project resolution and presets
24
+
25
+ `cookbook()` and CLI commands discover the same `docs.config.ts`. Set `root`
26
+ to a directory relative to this file to change where content, local assets,
27
+ and the lock live. `--root` chooses the CLI's configuration search directory;
28
+ `--config` chooses a config file. An inline integration `config` object skips
29
+ discovery and resolves its `root` relative to the integration root.
30
+
31
+ Use `mergeDocsConfig(preset, overrides)` to compose shared configuration. Objects
32
+ merge recursively and arrays replace; Tasty styles preserve default values when
33
+ adding conditional overrides. Neither input is mutated. See
34
+ [working examples](./examples.md#share-configuration-and-themes).
35
+
36
+ ## Redirects
37
+
38
+ Map old routes to collected document routes:
39
+
40
+ ```ts
41
+ redirects: { "/old-guide": "/getting-started" }
42
+ ```
43
+
44
+ Pages can also declare `aliases: ["/old-guide"]` in frontmatter. Page aliases are
45
+ relative to the source mount. Cookbook rejects collisions, cycles, and missing
46
+ targets, collapses chains, and lets Astro emit static redirects. Internal links
47
+ using an alias are rewritten to the canonical route.
48
+
49
+ ## Site
50
+
51
+ ```ts
52
+ site: {
53
+ title: "Example Project",
54
+ version: "1.2.3",
55
+ description: "Documentation for Example Project",
56
+ url: "https://docs.example.com",
57
+ repository: "https://github.com/example/project",
58
+ favicon: "./assets/brand.svg"
59
+ }
60
+ ```
61
+
62
+ `version` is the documented package version shown beside the site title. A site
63
+ with one locked npm package source infers its version automatically; set this
64
+ field for local or multi-package documentation. Read it from the package
65
+ manifest when possible so it remains current. `url` configures Astro's canonical
66
+ site origin and sitemap metadata. If Astro also declares `site`, the values must
67
+ match. `repository` adds a source link to the header.
68
+
69
+ ### Site icons
70
+
71
+ Cookbook ships its book mark as the default favicon. Set `site.favicon` to a
72
+ local SVG, PNG, JPEG, WebP, AVIF, or GIF when the documentation should use the
73
+ project's own artwork:
74
+
75
+ ```ts
76
+ site: {
77
+ title: "Example Project",
78
+ favicon: {
79
+ source: "./assets/brand.svg",
80
+ background: "#315efb"
81
+ }
82
+ }
83
+ ```
84
+
85
+ Paths are resolved from the project root. The string shorthand sets only the
86
+ source, as in `favicon: "./assets/brand.svg"`. `background` controls the opaque
87
+ canvas used for the Apple touch icon and maskable application icons; it defaults
88
+ to Cookbook blue.
89
+
90
+ At development and build time, Cookbook creates a scalable favicon when the
91
+ source is SVG, a 32×32 PNG fallback, a 180×180 Apple touch icon, 192×192 and
92
+ 512×512 application icons, safe-zone maskable variants, and a web app manifest.
93
+ It also emits modern `rel="icon"`, `rel="apple-touch-icon"`, and
94
+ `rel="manifest"` links plus light and dark `theme-color` metadata. Generated
95
+ files live under `/_cookbook/icons/`, respect Astro's `base`, and do not modify
96
+ the project's `public/` directory. The maskable variants render the source artwork
97
+ at 80% of the canvas on the configured opaque background.
98
+
99
+ These outputs follow current browser guidance for
100
+ [multiple icon formats and sizes](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/How_to/Define_app_icons),
101
+ [manifest icon purposes](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/icons),
102
+ and the
103
+ [180×180 Apple touch icon](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html).
104
+
105
+ ## Head
106
+
107
+ Add custom elements to every page's `<head>` with the `head` array. This is the
108
+ preferred configuration for analytics scripts and other remote resources:
109
+
110
+ ```ts
111
+ head: [
112
+ {
113
+ tag: "script",
114
+ attrs: {
115
+ defer: true,
116
+ src: "https://analytics.example.com/script.js",
117
+ "data-website-id": "YOUR-WEBSITE-ID",
118
+ },
119
+ },
120
+ ],
121
+ ```
122
+
123
+ Each entry accepts a `tag`, optional string or boolean `attrs`, and optional
124
+ string `content`. Cookbook renders these entries directly as HTML elements;
125
+ they do not pass through Astro's script or style processing. Use a `Head`
126
+ component override when a local asset needs Astro processing.
127
+
128
+ ## Page metadata
129
+
130
+ Enable source-aware edit links and Git timestamps for the page footer:
131
+
132
+ ```ts
133
+ editLink: {
134
+ baseUrl: "https://github.com/example/project/edit/main/"
135
+ },
136
+ lastUpdated: true,
137
+ ```
138
+
139
+ Cookbook joins `editLink.baseUrl` with each original repository-relative source
140
+ path, not a generated content-collection path. Set `editUrl: false` or
141
+ `lastUpdated: false` in a page's frontmatter to opt that page out; a string
142
+ `editUrl` or date-valued `lastUpdated` overrides the generated value. Package
143
+ sources show a timestamp only when their materialized file has Git history or
144
+ the page supplies one explicitly.
145
+
146
+ These settings intentionally mirror Starlight's
147
+ [`editLink`](https://starlight.astro.build/reference/configuration/#editlink)
148
+ and
149
+ [`lastUpdated`](https://starlight.astro.build/reference/configuration/#lastupdated)
150
+ configuration while preserving Cookbook's original source paths.
151
+
152
+ Cookbook also accepts Starlight-compatible page presentation frontmatter:
153
+
154
+ ```yaml
155
+ tableOfContents:
156
+ minHeadingLevel: 2
157
+ maxHeadingLevel: 4
158
+ pagefind: true
159
+ banner:
160
+ content: This API is experimental.
161
+ hero:
162
+ image:
163
+ file: ./assets/product.svg
164
+ sidebar:
165
+ label: Quick start
166
+ order: 1
167
+ group: Guides
168
+ ```
169
+
170
+ Set `sidebar: false` to omit a page from generated sidebars. `label`, `order`,
171
+ and `group` affect both the default sidebar and autogenerated navigation
172
+ directories. Relative hero images are validated, content-hashed, and copied
173
+ with the page's other local assets. Unrecognized frontmatter is preserved as graph entry `metadata`, outside the
174
+ renderer frontmatter. Use `content.frontmatter: "reject"` to reject unrelated
175
+ fields. Other supported fields include `aliases`, `template`, `hero`, `editUrl`,
176
+ `lastUpdated`, `prev`, `next`, `head`, `draft`, and `slug`.
177
+
178
+ ## Languages
179
+
180
+ Expose Starlight's multilingual routing and language picker directly:
181
+
182
+ ```ts
183
+ locales: {
184
+ root: { label: "English", lang: "en" },
185
+ fr: { label: "Français", lang: "fr" },
186
+ ar: { label: "العربية", lang: "ar", dir: "rtl" }
187
+ },
188
+ defaultLocale: "root",
189
+ ```
190
+
191
+ Locale keys other than `root` are URL prefixes. A source routed to `/fr/guide`
192
+ is the French counterpart of `/guide`; `defaultLocale` provides fallback
193
+ content when a translated route is missing. See Starlight's
194
+ [internationalization guide](https://starlight.astro.build/guides/i18n/) for
195
+ the shared routing and fallback behavior.
196
+
197
+ ## Content
198
+
199
+ ```ts
200
+ content: {
201
+ sources: [
202
+ { file: "README.md", route: "/" },
203
+ { glob: "docs/**/*.{md,mdx}", base: "docs" }
204
+ ],
205
+ allowOutsideRoot: false,
206
+ localizeRepositoryLinks: false,
207
+ frontmatter: "preserve"
208
+ }
209
+ ```
210
+
211
+ See [Content sources](./content-sources.md) for every declaration and its route
212
+ rules. Enable `localizeRepositoryLinks` to turn absolute repository `blob`,
213
+ `tree`, `raw`, or Bitbucket `src` links back into local Cookbook routes when a
214
+ matching page was collected. Cookbook uses `site.repository` for local sources
215
+ and each package manifest's `repository` metadata for package sources.
216
+
217
+ ## Navigation
218
+
219
+ Navigation can mix direct routes, nested groups, autogenerated directories,
220
+ and external links. Groups are recursive and can be nested to any practical
221
+ depth. Use the object form to add an optional primary tab row above the
222
+ documentation shell:
223
+
224
+ ```ts
225
+ navigation: {
226
+ tabs: [
227
+ {
228
+ label: "Guides",
229
+ link: "/",
230
+ items: [
231
+ "/",
232
+ {
233
+ label: "Build",
234
+ items: [
235
+ {
236
+ label: "Frontend",
237
+ items: [
238
+ {
239
+ label: "Frameworks",
240
+ items: ["/react", "/vue"]
241
+ }
242
+ ]
243
+ }
244
+ ]
245
+ }
246
+ ]
247
+ },
248
+ {
249
+ label: "API",
250
+ link: "/reference",
251
+ items: [
252
+ {
253
+ label: "Reference",
254
+ autogenerate: { directory: "/reference" }
255
+ }
256
+ ]
257
+ },
258
+ { label: "Playground", link: "https://example.com/playground" }
259
+ ],
260
+ items: [
261
+ "/",
262
+ {
263
+ label: "Start here",
264
+ items: ["/getting-started", "/configuration"]
265
+ },
266
+ {
267
+ label: "Reference",
268
+ autogenerate: { directory: "/reference" }
269
+ }
270
+ ]
271
+ }
272
+ ```
273
+
274
+ Give a group an optional `link` to use its header as a parent page:
275
+
276
+ ```ts
277
+ {
278
+ label: "Charts",
279
+ link: "/charts",
280
+ items: [
281
+ {
282
+ label: "Chart types",
283
+ link: "/charts/types",
284
+ autogenerate: { directory: "/charts/types" }
285
+ }
286
+ ]
287
+ }
288
+ ```
289
+
290
+ Group links must name existing root-relative page routes, without the deployment
291
+ base, a query, or a fragment. The parent page is omitted from its children if it
292
+ also appears in the manual list or autogenerated directory. It remains in
293
+ previous/next page navigation. A group with no remaining children becomes a
294
+ regular page link.
295
+
296
+ Top-level sections stay flat; their linked headings navigate to their pages.
297
+ For nested groups, clicking an unselected header or its chevron selects the parent
298
+ page and opens its children, keeping them open if already expanded. Clicking the
299
+ selected parent toggles its children without reloading. Selecting and collapsing
300
+ an open, unselected group therefore takes two clicks. Enter and Space work too, while modified clicks and opening a link
301
+ in a new tab retain normal link behavior. Groups without a `link` only toggle.
302
+ Only the selected page is highlighted; its ancestors keep their normal styling.
303
+
304
+ Tabs are omitted when `tabs` is not set. Give a tab `items` to replace the
305
+ sidebar for that section. Those items also establish section membership, so a
306
+ tab can own routes that do not share its URL prefix. A tab stays active for
307
+ pages nested below its link; `/` matches only the home page. When multiple tabs
308
+ could match, an exact tab link wins, followed by the longest link prefix and
309
+ then sidebar membership. Tabs without `items` use the top-level `items`
310
+ fallback. Every internal route named anywhere in navigation must exist.
311
+
312
+ ## Theme
313
+
314
+ ```ts
315
+ theme: {
316
+ brand: {
317
+ from: "#2f5bff",
318
+ contrast: { apca: 45 }
319
+ },
320
+ palette: {
321
+ surface: "#fcfcff",
322
+ text: "#20232a",
323
+ textSoft: "#626875"
324
+ },
325
+ tokens: {
326
+ "$radius": "8px",
327
+ "$card-radius": "16px",
328
+ "$border-width": "1px",
329
+ "$layout-width": "87.5rem",
330
+ "$content-width": "58rem",
331
+ "$sidebar-width": "17.5rem"
332
+ },
333
+ states: {},
334
+ presets: {
335
+ body: { fontFamily: "Inter, sans-serif", boldFontWeight: 680 },
336
+ heading: {
337
+ fontFamily: "Newsreader, serif",
338
+ fontWeight: 650,
339
+ boldFontWeight: 740
340
+ }
341
+ },
342
+ styles: {
343
+ ThemeSelect: {
344
+ Select: { border: "#border-strong" },
345
+ Picker: { shadow: "0 1rem 3rem #shadow" }
346
+ }
347
+ },
348
+ contrastLevel: "auto"
349
+ }
350
+ ```
351
+
352
+ The default brand is `okhsl(266 68% 48%)`, a blue with 68% saturation; controls
353
+ use an `8px` radius and cards use `16px`. Onest is the default body and heading family, while JetBrains Mono is
354
+ used for code. The default layout is capped at `87.5rem` (1400px), matching the
355
+ Tasty site, with a `58rem` reading column and a `17.5rem` sidebar. `palette`
356
+ supplies semantic Glaze inputs rather than component colors,
357
+ so the whole interface continues to adapt in dark and high-contrast modes. A requested APCA floor below 45 requires the explicit
358
+ `unsafeContrast: true` escape hatch. Learn more in
359
+ [Theme and components](./theme-and-components.md).
360
+
361
+ `theme.styles` is keyed by Cookbook UI surface name. A plain Tasty style object
362
+ contains only the properties to override; Cookbook deep-merges it into that
363
+ surface's complete base object internally. Unknown built-in names and sub-elements are rejected. Register custom
364
+ component names and their overrides in `theme.customStyles`. Structural Astro overrides under
365
+ `components.overrides` remain available when styling alone is insufficient.
366
+ `theme.states` registers additional Tasty state shorthands, and `contrastLevel`
367
+ is forwarded to Glaze's palette resolution.
368
+ The built-in documentation navigation surfaces are available as `Sidebar`,
369
+ `TableOfContents`, `MobileMenuToggle`, and `MobileNavigationTabs`; see
370
+ [Theme and components](./theme-and-components.md#style-customization) for their
371
+ complete sub-element lists.
372
+
373
+ ## Markdown
374
+
375
+ ```ts
376
+ markdown: {
377
+ stripLeadingBadges: true,
378
+ rawHtml: "sanitize",
379
+ }
380
+ ```
381
+
382
+ `stripLeadingBadges` removes badge-only paragraphs at the start of a page and
383
+ defaults to `true`. `rawHtml` accepts `"allow"`, `"sanitize"`, `"strip"`, or `"reject"`.
384
+ The default `sanitize` policy preserves safe elements, including `details`,
385
+ `summary`, tables, and inline emphasis, while removing executable markup,
386
+ event handlers, and presentational attributes. Links and images in sanitized
387
+ HTML pass through the content graph. `strip` removes HTML with a warning,
388
+ `allow` preserves trusted HTML, and `reject` reports a graph error. Package Markdown in safe mode is
389
+ always sanitized even when the global policy is `"allow"`, and package MDX
390
+ requires an explicit `trust: "mdx"` source declaration.
391
+
392
+ Configure renderer-level Markdown options such as custom remark or rehype
393
+ plugins and Shiki languages through Astro's top-level `markdown` configuration.
394
+ Cookbook preserves those settings while adding its own build-time transforms.
395
+
396
+ Cookbook renders fenced `mermaid` blocks as responsive, theme-aware SVG during
397
+ the static build. Flowcharts, state, sequence, class, and entity-relationship
398
+ diagrams are supported. Invalid or unsupported diagrams remain visible as
399
+ source code.
400
+
401
+ ````markdown
402
+ ```mermaid
403
+ flowchart TD
404
+ accTitle: Proposal workflow
405
+ accDescr: Evidence is inspected before proposals are decided and applied.
406
+ inspect[Inspect evidence] --> seal[Seal proposals]
407
+ seal --> decide[Decide eligible items]
408
+ decide --> apply[Apply accepted items]
409
+ ```
410
+ ````
411
+
412
+ ```mermaid
413
+ flowchart TD
414
+ accTitle: Proposal workflow
415
+ accDescr: Evidence is inspected before proposals are decided and applied.
416
+ inspect[Inspect evidence] --> seal[Seal proposals]
417
+ seal --> decide[Decide eligible items]
418
+ decide --> apply[Apply accepted items]
419
+ ```
420
+
421
+ ## Search
422
+
423
+ ```ts
424
+ search: {
425
+ enabled: true,
426
+ },
427
+ ```
428
+
429
+ Search is generated locally with Pagefind during a static build. Disable it
430
+ for hosts or fixtures that do not need an index.
431
+
432
+ ## Components
433
+
434
+ ```ts
435
+ components: {
436
+ overrides: {
437
+ Header: "./src/components/Header.astro",
438
+ Footer: "./src/components/Footer.astro"
439
+ }
440
+ }
441
+ ```
442
+
443
+ Component replacement is the advanced escape hatch. Prefer theme tokens and
444
+ named styles for visual changes that do not need new structure.
445
+
446
+ Cookbook uses its built-in footer by default, including the “Generated with
447
+ Cookbook” credit. Replace the complete footer with the `Footer` component path
448
+ shown above, or remove it with:
449
+
450
+ ```ts
451
+ components: {
452
+ overrides: {
453
+ Footer: false,
454
+ },
455
+ },
456
+ ```
457
+
458
+ Disabling the complete footer also removes its edit link, last-updated metadata,
459
+ and previous/next-page navigation.
460
+
461
+ ## Build
462
+
463
+ ```ts
464
+ build: {
465
+ strict: true,
466
+ ci: process.env.CI === "true",
467
+ cacheDir: "",
468
+ maxArtifactBytes: 25 * 1024 * 1024,
469
+ maxUnpackedBytes: 100 * 1024 * 1024,
470
+ maxFiles: 10_000,
471
+ maxPathDepth: 24,
472
+ maxAssetBytes: 20 * 1024 * 1024
473
+ }
474
+ ```
475
+
476
+ `strict` makes missing internal links errors instead of warnings. `ci` makes
477
+ missing heading fragments errors and defaults to `true` when `CI=true`.
478
+ Cookbook derives its public base path from Astro's top-level `base` setting so
479
+ routes and assets cannot drift between two configurations. An empty `cacheDir`
480
+ uses `~/.cache/cookbook`; set an explicit path to relocate downloaded package
481
+ artifacts. Package limits protect builds from unexpected registry artifacts;
482
+ raise them deliberately for a reviewed package.
483
+
484
+ ## Header buttons
485
+
486
+ Configure the top bar with `site.headerLinks`. Links appear beside search on
487
+ larger screens and in a More popover below 50rem. The desktop header supports
488
+ primary buttons; More uses a compact, left-aligned list of uniform navigation
489
+ links. Omit the array (or use `[]`) to hide More.
490
+
491
+ ```ts
492
+ export default defineDocsConfig({
493
+ site: {
494
+ headerLinks: [
495
+ {
496
+ label: "Changelog",
497
+ link: "https://example.com/changelog",
498
+ newTab: true,
499
+ },
500
+ { label: "Get started", link: "/getting-started", variant: "primary" },
501
+ ],
502
+ },
503
+ });
504
+ ```
505
+
506
+ Each entry requires a non-empty `label` and a `link` (an HTTP(S) URL,
507
+ root-relative route, or fragment). Cookbook prefixes root-relative links with
508
+ the Astro base. `variant` is `default` or `primary` and applies on desktop;
509
+ `newTab` defaults to false
510
+ and adds safe new-window attributes when enabled. Customize the complete
511
+ button and popover style tree through `theme.styles.HeaderLinks`.
512
+
513
+ `theme.palette.header` sets the translucent header's color seed. It defaults
514
+ to `theme.palette.surface`; Glaze resolves it for light, dark, and both high
515
+ contrast modes. Adjust blur and other header styling via `theme.styles.HeaderFrame`.
516
+ `theme.palette.overlay` controls the fixed underlay color, defaulting to black at
517
+ 50% opacity in every scheme. The mobile drawer uses the Glaze shadow token and
518
+ a 120ms slide transition; customize these through `theme.styles.Sidebar`.
@@ -0,0 +1,150 @@
1
+ ---
2
+ title: Content sources
3
+ description: Collect local files, globs, and locked npm package documentation into one route graph.
4
+ sidebar:
5
+ order: 3
6
+ ---
7
+
8
+ Cookbook first collects every source and assigns each one a canonical route.
9
+ Only then does it rewrite links and assets. That two-phase graph lets pages
10
+ link across directories and source declarations without depending on discovery
11
+ order.
12
+
13
+ ## Convention mode
14
+
15
+ When `content.sources` is omitted, Cookbook includes these sources when they
16
+ exist:
17
+
18
+ ```ts
19
+ [
20
+ { file: "README.md", route: "/" },
21
+ { glob: "docs/**/*.{md,mdx}", base: "docs" },
22
+ ];
23
+ ```
24
+
25
+ Files or directories beginning with `_` are excluded from glob discovery.
26
+ Explicit `content.sources` replace these conventions.
27
+
28
+ ## Local files
29
+
30
+ Use a file declaration for a single document with an optional explicit route
31
+ or inferred metadata:
32
+
33
+ ```ts
34
+ {
35
+ file: "README.md",
36
+ route: "/",
37
+ title: "Product documentation",
38
+ description: "Learn how to use the product."
39
+ }
40
+ ```
41
+
42
+ Use a glob for a documentation tree:
43
+
44
+ ```ts
45
+ {
46
+ glob: ["docs/**/*.md", "docs/**/*.mdx"],
47
+ base: "docs",
48
+ routeBase: "/",
49
+ exclude: ["docs/internal/**"]
50
+ }
51
+ ```
52
+
53
+ `base` is removed from generated routes. `routeBase` is then prepended. A
54
+ directory `README.md` or `index.md` maps to the directory route; other pages
55
+ use extensionless routes.
56
+
57
+ | Source path | `base` | `routeBase` | Route |
58
+ | -------------------- | ------ | ------------ | ---------------------------- |
59
+ | `README.md` | — | — | `/` when explicitly assigned |
60
+ | `docs/setup.md` | `docs` | — | `/setup` |
61
+ | `docs/api/index.md` | `docs` | — | `/api` |
62
+ | `docs/api/client.md` | `docs` | `/reference` | `/reference/api/client` |
63
+
64
+ Source paths are resolved from the configured project root. Paths outside that
65
+ root are rejected unless `content.allowOutsideRoot` is explicitly enabled.
66
+ Prefer an explicit source `root` when documenting another package; file and
67
+ glob paths, links, and assets are confined to that declared source root.
68
+
69
+ ## Source identities and repeated mounts
70
+
71
+ Every source can have an `id` containing letters, digits, underscores, and
72
+ hyphens. Without one, Cookbook uses `source-1`, `source-2`, and so on. Explicit
73
+ IDs are stable when declarations are reordered and must be unique.
74
+
75
+ ```ts
76
+ content: {
77
+ sources: [
78
+ { id: "v1", root: "versions/v1", glob: "**/*.md", routeBase: "/v1" },
79
+ { id: "v2", root: "versions/v2", glob: "**/*.md", routeBase: "/v2" },
80
+ ];
81
+ }
82
+ ```
83
+
84
+ The same files may appear in several mounts. Relative links prefer the current
85
+ source; an unambiguous page in another source can also resolve by file path.
86
+ Use `source:v2/guide.md` to select another mount explicitly. The path is relative
87
+ to that source's root, before `base` is removed from routes. Queries and heading
88
+ fragments are preserved.
89
+
90
+ A frontmatter `slug` is relative to `routeBase`, including when it begins with
91
+ `/`. For example, `slug: intro` under `/v2` creates `/v2/intro`. File sources also
92
+ accept `routeBase`, which prefixes their explicit `route`. Empty `sources: []`
93
+ means no sources; omit the property to enable conventions.
94
+
95
+ ## npm package sources
96
+
97
+ Package sources read documentation from the actual npm artifact:
98
+
99
+ ```ts
100
+ {
101
+ package: "@scope/package@latest",
102
+ include: ["README.md", "docs/**/*.md"],
103
+ exclude: ["docs/internal/**"],
104
+ index: "README.md",
105
+ routeBase: "/"
106
+ }
107
+ ```
108
+
109
+ Run `cookbook update` to create or reconcile the lock after editing sources.
110
+ A production build uses the exact requested specifier, version, and integrity stored in
111
+ `cookbook.lock.json`. The package creator writes this lock automatically.
112
+ Artifacts are integrity-checked, extracted with file-count and size limits,
113
+ and cached by integrity.
114
+
115
+ Package Markdown is untrusted by default. Raw HTML is sanitized to safe
116
+ elements, HTML-capable frontmatter is stripped, custom `head` entries are discarded,
117
+ unsafe URL protocols are rejected, and MDX cannot execute. Set `trust: "mdx"`
118
+ only after reviewing the exact locked artifact; doing so allows its build-time
119
+ code to run. Trusted MDX is compiled by Starlight, including relative component
120
+ imports from the source file's directory. Package-provided indexes, include
121
+ patterns, exclude patterns, and every discovered file are confined to the
122
+ extracted artifact root.
123
+
124
+ ## Links and assets
125
+
126
+ Write ordinary repository-relative Markdown:
127
+
128
+ ```md
129
+ [Install](./getting-started.md)
130
+ ![Architecture](./assets/architecture.svg)
131
+ ```
132
+
133
+ Known document links are rewritten to public routes. Query strings and heading
134
+ fragments are preserved, and fragments are checked against the target page's
135
+ GitHub-style heading IDs. Inline and reference-style links and images are
136
+ supported. Local images and downloadable files are validated, content-hashed,
137
+ and copied into the static build.
138
+
139
+ Absolute web links, `mailto:`, `tel:`, and hash-only links remain unchanged by
140
+ default. Set `content.localizeRepositoryLinks: true` to rewrite absolute links
141
+ back into the collected documentation when they match `site.repository` or the
142
+ current package's `repository` manifest field. GitHub/GitLab `blob`, `tree`, and
143
+ `raw` URLs plus Bitbucket `src` URLs are recognized; query strings and fragments
144
+ are preserved. Links without a matching collected page remain external.
145
+
146
+ Missing relative links are errors in strict mode; missing assets and paths
147
+ escaping an allowed source root are always errors.
148
+
149
+ Run the [doctor command](./cli.md#validate-with-doctor) before committing a
150
+ large content move.