blume 0.6.0 → 0.6.2
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.
- package/dist/cli/index.js +6070 -5718
- package/dist/cli/index.js.map +41 -40
- package/dist/types/core/config-input.d.ts +749 -0
- package/dist/types/core/config.d.ts +126 -3
- package/dist/types/core/schema.d.ts +10 -27
- package/dist/types/core/sources/types.d.ts +6 -0
- package/dist/types/index.d.ts +2 -1
- package/docs/advanced/changelog.mdx +10 -2
- package/docs/configuration/index.mdx +0 -2
- package/docs/content/syntax.mdx +4 -8
- package/package.json +1 -1
- package/src/astro/generate.ts +59 -24
- package/src/astro/markdown-negotiation.ts +12 -3
- package/src/astro/templates.ts +94 -12
- package/src/cli/commands/build.ts +26 -1
- package/src/cli/commands/dev.ts +30 -14
- package/src/cli/commands/doctor.ts +35 -7
- package/src/cli/commands/sync.ts +14 -2
- package/src/cli/dev-lock.ts +40 -10
- package/src/cli/env.ts +5 -1
- package/src/components/content/Update.astro +12 -2
- package/src/components/content/changelog-element.ts +62 -0
- package/src/components/islands/ask-ai.tsx +3 -1
- package/src/components/islands/hooks.ts +5 -1
- package/src/components/layout/Header.astro +10 -2
- package/src/components/layout/NavSelector.astro +5 -3
- package/src/components/layout/PageLayout.astro +2 -1
- package/src/components/layout/ReferenceLayout.astro +1 -0
- package/src/components/layout/RootLayout.astro +47 -10
- package/src/components/layout/Search.astro +8 -3
- package/src/components/layout/nav-utils.ts +7 -3
- package/src/core/config-input.ts +923 -0
- package/src/core/config.ts +126 -3
- package/src/core/i18n.ts +6 -5
- package/src/core/links.ts +16 -1
- package/src/core/meta.ts +112 -52
- package/src/core/navigation.ts +15 -5
- package/src/core/project-graph.ts +68 -2
- package/src/core/schema.ts +8 -14
- package/src/core/sources/assets.ts +21 -5
- package/src/core/sources/cache.ts +19 -1
- package/src/core/sources/github-releases.ts +9 -3
- package/src/core/sources/mdx-remote.ts +14 -4
- package/src/core/sources/normalize.ts +13 -1
- package/src/core/sources/notion.ts +43 -7
- package/src/core/sources/resolve.ts +44 -1
- package/src/core/sources/sanity.ts +9 -3
- package/src/core/sources/types.ts +6 -0
- package/src/deploy/adapter-output.ts +82 -0
- package/src/deploy/rss.ts +3 -1
- package/src/index.ts +1 -1
- package/src/markdown/code-title.ts +11 -4
- package/src/markdown/index.ts +28 -30
- package/src/markdown/math.ts +3 -2
- package/src/markdown/package-commands.ts +13 -0
- package/src/og/card.ts +3 -1
- package/src/openapi/model.ts +2 -1
- package/src/openapi/parse.ts +9 -1
- package/src/openapi/references.ts +11 -1
- package/src/openapi/render-mdx.ts +30 -3
- package/src/openapi/source.ts +3 -1
- package/src/registry/eject.ts +21 -14
- package/src/search/documents.ts +4 -1
- package/src/theme/entry.ts +10 -3
- package/src/theme/icons.ts +7 -11
|
@@ -0,0 +1,923 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import type { FontSlug } from "../theme/fonts.ts";
|
|
4
|
+
import type {
|
|
5
|
+
blumeConfigSchema,
|
|
6
|
+
OpenApiSource,
|
|
7
|
+
SearchProvider,
|
|
8
|
+
SidebarDisplay,
|
|
9
|
+
SidebarItemConfig,
|
|
10
|
+
} from "./schema.ts";
|
|
11
|
+
import type { ContentSource } from "./sources/types.ts";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The public, hand-documented authoring type for `blume.config.ts`.
|
|
15
|
+
*
|
|
16
|
+
* This interface mirrors the input side of {@link blumeConfigSchema} — the Zod
|
|
17
|
+
* schema is still the single source of validation truth, but the schema's
|
|
18
|
+
* inferred type carries no doc comments, so this parallel interface exists
|
|
19
|
+
* purely to give editors rich per-field hover text and autocomplete. A
|
|
20
|
+
* compile-time guard at the bottom of this file fails `tsc` if the two ever
|
|
21
|
+
* drift, so keep them in sync.
|
|
22
|
+
*
|
|
23
|
+
* @see {@link defineConfig} — the helper you actually call.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Small shared helpers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A literal union that still accepts any other string, so known values
|
|
32
|
+
* autocomplete without rejecting custom ones (matches the schema's `string`).
|
|
33
|
+
*/
|
|
34
|
+
type LiteralUnion<T extends string> = T | (string & Record<never, never>);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A per-color-mode value: a single string applies to both light and dark; the
|
|
38
|
+
* object form sets each mode independently (either key may be omitted to
|
|
39
|
+
* override just one mode).
|
|
40
|
+
*/
|
|
41
|
+
export type PerModeValue = string | { dark?: string; light?: string };
|
|
42
|
+
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Brand: logo & banner
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
/** The logo mark: a single image path/URL, or per-mode variants with alt text. */
|
|
48
|
+
export type LogoImage =
|
|
49
|
+
| string
|
|
50
|
+
| {
|
|
51
|
+
/** Alt text for the mark. */
|
|
52
|
+
alt?: string;
|
|
53
|
+
/** Image shown in dark mode. */
|
|
54
|
+
dark?: string;
|
|
55
|
+
/** Image shown in light mode. */
|
|
56
|
+
light?: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Site logo. A bare string is the image shorthand. The object form splits the
|
|
61
|
+
* brand into an optional `image` mark and an optional wordmark `text`, so a site
|
|
62
|
+
* can show an image-only logo, a text-only logo, or both.
|
|
63
|
+
*/
|
|
64
|
+
export type LogoConfig =
|
|
65
|
+
| string
|
|
66
|
+
| {
|
|
67
|
+
/** Overrides the brand link target. Defaults to `/`. */
|
|
68
|
+
href?: string;
|
|
69
|
+
/** The logo mark. Omit for a text-only brand. */
|
|
70
|
+
image?: LogoImage;
|
|
71
|
+
/**
|
|
72
|
+
* Wordmark text beside the mark. Omit to fall back to the site `title`;
|
|
73
|
+
* set to `""` to render the mark alone.
|
|
74
|
+
*/
|
|
75
|
+
text?: string;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Site-wide announcement banner shown above the header. A bare string is the
|
|
80
|
+
* banner text; the object form adds an optional call-to-action link and
|
|
81
|
+
* dismiss behavior.
|
|
82
|
+
*/
|
|
83
|
+
export type BannerConfig =
|
|
84
|
+
| string
|
|
85
|
+
| {
|
|
86
|
+
/** The banner message. */
|
|
87
|
+
content: string;
|
|
88
|
+
/** Show a dismiss button; the choice is remembered per visitor. */
|
|
89
|
+
dismissible?: boolean;
|
|
90
|
+
/** Stable key for remembering dismissal; defaults to the content. */
|
|
91
|
+
id?: string;
|
|
92
|
+
/** An optional call-to-action link. */
|
|
93
|
+
link?: {
|
|
94
|
+
/** Link target (internal route or external URL). */
|
|
95
|
+
href: string;
|
|
96
|
+
/** Link text. */
|
|
97
|
+
text: string;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Content sources
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
/** Local Markdown/MDX read from the filesystem. */
|
|
106
|
+
export interface FilesystemSource {
|
|
107
|
+
type: "filesystem";
|
|
108
|
+
/** Glob patterns to ignore. Defaults to `["**\/_*", "**\/.*"]`. */
|
|
109
|
+
exclude?: string[];
|
|
110
|
+
/** Glob patterns to include. Defaults to `["**\/*.{md,mdx}"]`. */
|
|
111
|
+
include?: string[];
|
|
112
|
+
/** Namespaces this source's routes under `/<prefix>/`. */
|
|
113
|
+
prefix?: string;
|
|
114
|
+
/** Directory to read from, relative to the project root. Defaults to `docs`. */
|
|
115
|
+
root?: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Remote Markdown/MDX fetched over HTTP. Enumerate files explicitly against a
|
|
120
|
+
* raw `url` base, or from a GitHub repo subtree via `github`. A private repo's
|
|
121
|
+
* token comes from `GITHUB_TOKEN` — never inline it here.
|
|
122
|
+
*/
|
|
123
|
+
export interface MdxRemoteSource {
|
|
124
|
+
type: "mdx-remote";
|
|
125
|
+
/** Explicit list of source-relative file paths to fetch from `url`. */
|
|
126
|
+
files?: string[];
|
|
127
|
+
/** Enumerate a GitHub repo subtree via the git-trees API. */
|
|
128
|
+
github?: {
|
|
129
|
+
/** Repository owner (user or org). */
|
|
130
|
+
owner: string;
|
|
131
|
+
/** Subpath within the repo. Defaults to the repo root. */
|
|
132
|
+
path?: string;
|
|
133
|
+
/** Git ref (branch, tag, or SHA). Defaults to `main`. */
|
|
134
|
+
ref?: string;
|
|
135
|
+
/** Repository name. */
|
|
136
|
+
repo: string;
|
|
137
|
+
};
|
|
138
|
+
/** Glob patterns applied to enumerated refs. Defaults to `["**\/*.{md,mdx}"]`. */
|
|
139
|
+
include?: string[];
|
|
140
|
+
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
141
|
+
pollInterval?: number;
|
|
142
|
+
/** Namespaces this source's routes under `/<prefix>/`. */
|
|
143
|
+
prefix?: string;
|
|
144
|
+
/** Raw base URL, e.g. `https://raw.githubusercontent.com/acme/sdk/main/docs`. */
|
|
145
|
+
url?: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* A repo's GitHub Releases, materialized as `type: changelog` entries — release
|
|
150
|
+
* notes become the changelog with no files to maintain. A private repo reads a
|
|
151
|
+
* token from `GITHUB_TOKEN`; never inline it here.
|
|
152
|
+
*/
|
|
153
|
+
export interface GithubReleasesSource {
|
|
154
|
+
type: "github-releases";
|
|
155
|
+
/** Include draft releases (needs a token with repo write access). */
|
|
156
|
+
drafts?: boolean;
|
|
157
|
+
/** Cap the number of releases materialized, newest-first. Defaults to 100. */
|
|
158
|
+
limit?: number;
|
|
159
|
+
/** Repository owner (user or org). */
|
|
160
|
+
owner: string;
|
|
161
|
+
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
162
|
+
pollInterval?: number;
|
|
163
|
+
/** Namespaces this source's routes under `/<prefix>/`; e.g. `changelog`. */
|
|
164
|
+
prefix?: string;
|
|
165
|
+
/** Include prereleases. */
|
|
166
|
+
prereleases?: boolean;
|
|
167
|
+
/** Repository name. */
|
|
168
|
+
repo: string;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** A Sanity dataset queried with GROQ; Portable Text bodies become Markdown. */
|
|
172
|
+
export interface SanitySource {
|
|
173
|
+
type: "sanity";
|
|
174
|
+
/** Sanity API version (a date). Defaults to `2024-01-01`. */
|
|
175
|
+
apiVersion?: string;
|
|
176
|
+
/** Dataset name to query. */
|
|
177
|
+
dataset: string;
|
|
178
|
+
/** Field paths mapping a document onto Blume meta + body. */
|
|
179
|
+
fields?: {
|
|
180
|
+
/** Field holding the renderable body (Portable Text or Markdown). */
|
|
181
|
+
body?: string;
|
|
182
|
+
/** Field holding the page description. */
|
|
183
|
+
description?: string;
|
|
184
|
+
/** Field holding the last-modified date. */
|
|
185
|
+
lastModified?: string;
|
|
186
|
+
/** Field holding the page slug. */
|
|
187
|
+
slug?: string;
|
|
188
|
+
/** Field holding the page title. */
|
|
189
|
+
title?: string;
|
|
190
|
+
};
|
|
191
|
+
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
192
|
+
pollInterval?: number;
|
|
193
|
+
/** Namespaces this source's routes under `/<prefix>/`. */
|
|
194
|
+
prefix?: string;
|
|
195
|
+
/** Sanity project id. */
|
|
196
|
+
projectId: string;
|
|
197
|
+
/** GROQ query selecting the documents to import. */
|
|
198
|
+
query: string;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** A Notion database; pages become entries, blocks become MDX. */
|
|
202
|
+
export interface NotionSource {
|
|
203
|
+
type: "notion";
|
|
204
|
+
/** Notion database id. */
|
|
205
|
+
database: string;
|
|
206
|
+
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
207
|
+
pollInterval?: number;
|
|
208
|
+
/** Namespaces this source's routes under `/<prefix>/`. */
|
|
209
|
+
prefix?: string;
|
|
210
|
+
/** Notion property names mapped onto Blume meta. */
|
|
211
|
+
properties?: {
|
|
212
|
+
/** Property holding the page description. */
|
|
213
|
+
description?: string;
|
|
214
|
+
/** Property holding the sort order. */
|
|
215
|
+
order?: string;
|
|
216
|
+
/** Property holding the page slug. */
|
|
217
|
+
slug?: string;
|
|
218
|
+
/** Property holding the publish status. */
|
|
219
|
+
status?: string;
|
|
220
|
+
/** Property holding the page title. */
|
|
221
|
+
title?: string;
|
|
222
|
+
};
|
|
223
|
+
/** Status value treated as published; others map to `draft`. Defaults to `Published`. */
|
|
224
|
+
publishedValue?: string;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* A user-provided {@link ContentSource} instance, passed straight through. This
|
|
229
|
+
* is the extension point for adapters with custom serializers or any other
|
|
230
|
+
* backend, without their SDKs touching core.
|
|
231
|
+
*/
|
|
232
|
+
export interface CustomSource {
|
|
233
|
+
type: "custom";
|
|
234
|
+
/** A `ContentSource` implementation (an object with `name` + `load`). */
|
|
235
|
+
source: ContentSource;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** A single configured content source, discriminated by `type`. */
|
|
239
|
+
export type ContentSourceInput =
|
|
240
|
+
| FilesystemSource
|
|
241
|
+
| MdxRemoteSource
|
|
242
|
+
| GithubReleasesSource
|
|
243
|
+
| SanitySource
|
|
244
|
+
| NotionSource
|
|
245
|
+
| CustomSource;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Where content lives and how it's discovered. When `sources` is omitted, the
|
|
249
|
+
* top-level `root`/`include`/`exclude` desugar to one implicit filesystem
|
|
250
|
+
* source, so simple sites need nothing here.
|
|
251
|
+
*/
|
|
252
|
+
export interface ContentConfig {
|
|
253
|
+
/** Default page `type` for content that sets none. Defaults to `doc`. */
|
|
254
|
+
defaultType?: string;
|
|
255
|
+
/** Glob patterns to ignore. Defaults to `["**\/_*", "**\/.*"]`. */
|
|
256
|
+
exclude?: string[];
|
|
257
|
+
/** Glob patterns to include. Defaults to `["**\/*.{md,mdx}"]`. */
|
|
258
|
+
include?: string[];
|
|
259
|
+
/** Directory of standalone `pages` (outside the docs tree). Defaults to `pages`. */
|
|
260
|
+
pages?: string;
|
|
261
|
+
/** Content root directory, relative to the project root. Defaults to `docs`. */
|
|
262
|
+
root?: string;
|
|
263
|
+
/**
|
|
264
|
+
* Pluggable content sources. Mix local files with remote MDX, GitHub
|
|
265
|
+
* Releases, Sanity, Notion, or a custom `ContentSource`.
|
|
266
|
+
*/
|
|
267
|
+
sources?: ContentSourceInput[];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
// Navigation
|
|
272
|
+
// ---------------------------------------------------------------------------
|
|
273
|
+
|
|
274
|
+
/** A single item inside a header tab's dropdown. */
|
|
275
|
+
export interface NavTabItem {
|
|
276
|
+
/** Secondary line under the label. */
|
|
277
|
+
description?: string;
|
|
278
|
+
/** Lucide icon name shown beside the label. */
|
|
279
|
+
icon?: string;
|
|
280
|
+
/** Item label. */
|
|
281
|
+
label: string;
|
|
282
|
+
/** Route the item links to. */
|
|
283
|
+
path: string;
|
|
284
|
+
/** Short tag/pill (e.g. `New`, `Beta`). */
|
|
285
|
+
tag?: string;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** A top-level tab in the header, optionally opening a dropdown of items. */
|
|
289
|
+
export interface NavTab {
|
|
290
|
+
/** Lucide icon name shown beside the label. */
|
|
291
|
+
icon?: string;
|
|
292
|
+
/** Dropdown items; omit for a plain link tab. */
|
|
293
|
+
items?: NavTabItem[];
|
|
294
|
+
/** Tab label. */
|
|
295
|
+
label: string;
|
|
296
|
+
/** Route the tab links to. */
|
|
297
|
+
path: string;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** A single option in a header selector (version, language, product, …). */
|
|
301
|
+
export interface NavSelectorItem {
|
|
302
|
+
/** Secondary line under the label. */
|
|
303
|
+
description?: string;
|
|
304
|
+
/** Lucide icon name shown beside the label. */
|
|
305
|
+
icon?: string;
|
|
306
|
+
/** Option label. */
|
|
307
|
+
label: string;
|
|
308
|
+
/** Route the option links to. */
|
|
309
|
+
path: string;
|
|
310
|
+
/** Short tag/pill. */
|
|
311
|
+
tag?: string;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* A header dropdown for switching context — versions, languages, products, or a
|
|
316
|
+
* generic dropdown. `kind` drives the icon and a11y labeling.
|
|
317
|
+
*/
|
|
318
|
+
export interface NavSelector {
|
|
319
|
+
/** The options shown in the dropdown. */
|
|
320
|
+
items?: NavSelectorItem[];
|
|
321
|
+
/** What the selector switches between. */
|
|
322
|
+
kind: "dropdown" | "language" | "product" | "version";
|
|
323
|
+
/** Selector label / current value. */
|
|
324
|
+
label: string;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* A pinned link rendered above the sidebar sections — a blog, changelog, or
|
|
329
|
+
* contact page that stays reachable regardless of the active tab. `href` may be
|
|
330
|
+
* an internal route or an external URL.
|
|
331
|
+
*/
|
|
332
|
+
export interface FeaturedLink {
|
|
333
|
+
/** Link target. */
|
|
334
|
+
href: string;
|
|
335
|
+
/** Lucide icon name shown beside the label. */
|
|
336
|
+
icon?: string;
|
|
337
|
+
/** Link label. */
|
|
338
|
+
label: string;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* The sidebar. Omit `items` to generate the sidebar from the content tree;
|
|
343
|
+
* provide `items` for a fully explicit sidebar. `display` sets how every group
|
|
344
|
+
* renders by default (an individual group may override it). A bare array is
|
|
345
|
+
* shorthand for `{ items }`.
|
|
346
|
+
*/
|
|
347
|
+
export type SidebarConfig =
|
|
348
|
+
| SidebarItemConfig[]
|
|
349
|
+
| {
|
|
350
|
+
/**
|
|
351
|
+
* Default group rendering: `flat` (header + list), `group` (collapsible
|
|
352
|
+
* disclosure), or `page` (drill-in sub-panel). Defaults to `flat`.
|
|
353
|
+
*/
|
|
354
|
+
display?: SidebarDisplay;
|
|
355
|
+
/** Explicit sidebar nodes; omit to auto-generate from content. */
|
|
356
|
+
items?: SidebarItemConfig[];
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
/** Header, sidebar, tabs, and switcher configuration. */
|
|
360
|
+
export interface NavigationConfig {
|
|
361
|
+
/** Pinned links shown above the generated sidebar sections. */
|
|
362
|
+
featured?: FeaturedLink[];
|
|
363
|
+
/** Show a GitHub repo link in the header (requires `github` configured). */
|
|
364
|
+
repo?: boolean;
|
|
365
|
+
/** Context switchers shown in the header (versions, languages, …). */
|
|
366
|
+
selectors?: NavSelector[];
|
|
367
|
+
/** Sidebar behavior and (optionally) an explicit sidebar tree. */
|
|
368
|
+
sidebar?: SidebarConfig;
|
|
369
|
+
/** Top-level tabs shown in the header. */
|
|
370
|
+
tabs?: NavTab[];
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// ---------------------------------------------------------------------------
|
|
374
|
+
// Theme
|
|
375
|
+
// ---------------------------------------------------------------------------
|
|
376
|
+
|
|
377
|
+
/** The three type roles, each a curated Google Font slug. */
|
|
378
|
+
export interface FontsConfig {
|
|
379
|
+
/** Body / prose font. Defaults to `inter`. */
|
|
380
|
+
body?: LiteralUnion<FontSlug>;
|
|
381
|
+
/** Display / heading font. Defaults to `inter-tight`. */
|
|
382
|
+
display?: LiteralUnion<FontSlug>;
|
|
383
|
+
/** Monospace / code font. Defaults to `ibm-plex-mono`. */
|
|
384
|
+
mono?: LiteralUnion<FontSlug>;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/** Colors, fonts, radius, and color-mode behavior. */
|
|
388
|
+
export interface ThemeConfig {
|
|
389
|
+
/**
|
|
390
|
+
* Accent color. A palette name (`blue`, `violet`, `green`, …) or any CSS
|
|
391
|
+
* color applies to both modes; the object form sets each mode. Defaults to
|
|
392
|
+
* `blue`.
|
|
393
|
+
*/
|
|
394
|
+
accent?: string | { dark: string; light: string };
|
|
395
|
+
/** Optional distinct color for call-to-action surfaces. */
|
|
396
|
+
action?: string;
|
|
397
|
+
/** Page background color, per mode. */
|
|
398
|
+
background?: PerModeValue;
|
|
399
|
+
/** Page background image (CSS `background-image` value), per mode. */
|
|
400
|
+
backgroundImage?: PerModeValue;
|
|
401
|
+
/** Font selection for body, display, and mono roles. */
|
|
402
|
+
fonts?: FontsConfig;
|
|
403
|
+
/** Overall page layout. Currently only `sidebar`. */
|
|
404
|
+
layout?: "sidebar";
|
|
405
|
+
/** Initial color mode. Defaults to `system`. */
|
|
406
|
+
mode?: "system" | "light" | "dark";
|
|
407
|
+
/** Corner radius scale. Defaults to `md`. */
|
|
408
|
+
radius?: "none" | "sm" | "md" | "lg";
|
|
409
|
+
/**
|
|
410
|
+
* Strict token mode: fail rather than silently fall back when a theme token
|
|
411
|
+
* is missing. Defaults to `false`.
|
|
412
|
+
*/
|
|
413
|
+
strict?: boolean;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// ---------------------------------------------------------------------------
|
|
417
|
+
// Search
|
|
418
|
+
// ---------------------------------------------------------------------------
|
|
419
|
+
|
|
420
|
+
/** Public credentials for the Algolia backend (the sync key stays an env var). */
|
|
421
|
+
export interface AlgoliaSearch {
|
|
422
|
+
appId: string;
|
|
423
|
+
indexName: string;
|
|
424
|
+
searchApiKey: string;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Public credentials for the Orama Cloud backend. */
|
|
428
|
+
export interface OramaCloudSearch {
|
|
429
|
+
apiKey: string;
|
|
430
|
+
endpoint: string;
|
|
431
|
+
/** Index id used by the build-time sync (with `ORAMA_PRIVATE_API_KEY`). */
|
|
432
|
+
indexId?: string;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/** Connection details for a self-hosted or cloud Typesense backend. */
|
|
436
|
+
export interface TypesenseSearch {
|
|
437
|
+
collection: string;
|
|
438
|
+
host: string;
|
|
439
|
+
port?: number;
|
|
440
|
+
protocol?: "http" | "https";
|
|
441
|
+
searchApiKey: string;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** Mixedbread semantic search: the store the server endpoint queries. */
|
|
445
|
+
export interface MixedbreadSearch {
|
|
446
|
+
storeId: string;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Search backend. The default `orama` builds a local index at build time (and
|
|
451
|
+
* runs in dev); hosted providers need their credential block below. `none`
|
|
452
|
+
* disables search.
|
|
453
|
+
*/
|
|
454
|
+
export interface SearchConfig {
|
|
455
|
+
/** Algolia credentials (required when `provider` is `algolia`). */
|
|
456
|
+
algolia?: AlgoliaSearch;
|
|
457
|
+
/** Indexing behavior. */
|
|
458
|
+
indexing?: {
|
|
459
|
+
/** Include pages marked `hidden` in the search index. Defaults to `false`. */
|
|
460
|
+
includeHiddenPages?: boolean;
|
|
461
|
+
};
|
|
462
|
+
/** Mixedbread store (required when `provider` is `mixedbread`). */
|
|
463
|
+
mixedbread?: MixedbreadSearch;
|
|
464
|
+
/** Orama Cloud credentials (required when `provider` is `orama-cloud`). */
|
|
465
|
+
oramaCloud?: OramaCloudSearch;
|
|
466
|
+
/** Which backend powers search. Defaults to `orama`. */
|
|
467
|
+
provider?: SearchProvider;
|
|
468
|
+
/** Typesense credentials (required when `provider` is `typesense`). */
|
|
469
|
+
typesense?: TypesenseSearch;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// ---------------------------------------------------------------------------
|
|
473
|
+
// AI
|
|
474
|
+
// ---------------------------------------------------------------------------
|
|
475
|
+
|
|
476
|
+
/** An empty-state prompt shown before the first Ask AI question. */
|
|
477
|
+
export interface AskSuggestion {
|
|
478
|
+
/** Lucide icon name shown beside the suggestion. */
|
|
479
|
+
icon?: string;
|
|
480
|
+
/** The clickable suggestion text. */
|
|
481
|
+
label: string;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/** The Ask AI chat assistant. */
|
|
485
|
+
export interface AskConfig {
|
|
486
|
+
/**
|
|
487
|
+
* Name of the env var holding the provider API key. Each provider has a
|
|
488
|
+
* sensible default; set this only to override it.
|
|
489
|
+
*/
|
|
490
|
+
apiKeyEnv?: string;
|
|
491
|
+
/**
|
|
492
|
+
* Backend base URL. Required for `openai-compatible`; for named providers it
|
|
493
|
+
* overrides the built-in preset.
|
|
494
|
+
*/
|
|
495
|
+
baseUrl?: string;
|
|
496
|
+
/** Turn Ask AI on. Defaults to `false`. */
|
|
497
|
+
enabled?: boolean;
|
|
498
|
+
/** Model id to use. Defaults to `openai/gpt-5.5`. */
|
|
499
|
+
model?: string;
|
|
500
|
+
/** Which backend routes the request. Defaults to `gateway`. */
|
|
501
|
+
provider?:
|
|
502
|
+
| "gateway"
|
|
503
|
+
| "openrouter"
|
|
504
|
+
| "llmgateway"
|
|
505
|
+
| "inkeep"
|
|
506
|
+
| "openai-compatible";
|
|
507
|
+
/** Starter prompts shown before the first question. */
|
|
508
|
+
suggestions?: AskSuggestion[];
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/** AI-facing features: the Ask AI assistant and an `llms.txt` manifest. */
|
|
512
|
+
export interface AiConfig {
|
|
513
|
+
/** The Ask AI chat assistant. */
|
|
514
|
+
ask?: AskConfig;
|
|
515
|
+
/** Emit `llms.txt` (an index of the docs for LLMs). Defaults to `false`. */
|
|
516
|
+
llmsTxt?: boolean;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// ---------------------------------------------------------------------------
|
|
520
|
+
// Analytics
|
|
521
|
+
// ---------------------------------------------------------------------------
|
|
522
|
+
|
|
523
|
+
/** An arbitrary analytics `<script>`; set exactly one of `src` or `content`. */
|
|
524
|
+
export interface AnalyticsScript {
|
|
525
|
+
/** Extra attributes spread onto the `<script>` (e.g. `data-domain`, `id`). */
|
|
526
|
+
attributes?: Record<string, string>;
|
|
527
|
+
/** Inline script body. Mutually exclusive with `src`. */
|
|
528
|
+
content?: string;
|
|
529
|
+
/** External script URL. Mutually exclusive with `content`. */
|
|
530
|
+
src?: string;
|
|
531
|
+
/** Load strategy for an external script. */
|
|
532
|
+
strategy?: "async" | "defer";
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/** Analytics providers. Configure one, several, or none. */
|
|
536
|
+
export interface AnalyticsConfig {
|
|
537
|
+
/** PostHog product analytics. */
|
|
538
|
+
posthog?: {
|
|
539
|
+
/** API host (for self-hosted / EU). Defaults to PostHog cloud. */
|
|
540
|
+
host?: string;
|
|
541
|
+
/** Project API key. */
|
|
542
|
+
key: string;
|
|
543
|
+
};
|
|
544
|
+
/** Escape hatch for any other provider (Plausible, Fathom, GA, Umami, …). */
|
|
545
|
+
scripts?: AnalyticsScript[];
|
|
546
|
+
/** Enable Vercel Web Analytics. */
|
|
547
|
+
vercel?: boolean;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// ---------------------------------------------------------------------------
|
|
551
|
+
// MCP
|
|
552
|
+
// ---------------------------------------------------------------------------
|
|
553
|
+
|
|
554
|
+
/** Expose the docs as an MCP server for connecting agents. */
|
|
555
|
+
export interface McpConfig {
|
|
556
|
+
/** Turn the MCP server on. Defaults to `false`. */
|
|
557
|
+
enabled?: boolean;
|
|
558
|
+
/** Optional system hint passed to connecting agents. */
|
|
559
|
+
instructions?: string;
|
|
560
|
+
/** Server name shown to clients; defaults to the site title. */
|
|
561
|
+
name?: string;
|
|
562
|
+
/** Route the server mounts at. Defaults to `/mcp`. */
|
|
563
|
+
route?: string;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// ---------------------------------------------------------------------------
|
|
567
|
+
// i18n
|
|
568
|
+
// ---------------------------------------------------------------------------
|
|
569
|
+
|
|
570
|
+
/** A configured locale plus display metadata for the switcher. */
|
|
571
|
+
export interface LocaleConfigInput {
|
|
572
|
+
/** Locale code, e.g. `en`, `fr`, `pt-BR`. */
|
|
573
|
+
code: string;
|
|
574
|
+
/** Text direction; drives `<html dir>`. Defaults to `ltr`. */
|
|
575
|
+
dir?: "ltr" | "rtl";
|
|
576
|
+
/** Human-readable name shown in the switcher. */
|
|
577
|
+
label: string;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Internationalization. Opt-in: when omitted, Blume is single-locale. The
|
|
582
|
+
* default locale lives at the content root; other locales are top-level
|
|
583
|
+
* directories named by `code` (the `dir` parser) or filename suffixes (`dot`).
|
|
584
|
+
*/
|
|
585
|
+
export interface I18nConfig {
|
|
586
|
+
/** Locale rendered at the content root. Defaults to `en`. */
|
|
587
|
+
defaultLocale?: string;
|
|
588
|
+
/** Locale rendered for a missing translation; `null` disables fallback. */
|
|
589
|
+
fallbackLocale?: string | null;
|
|
590
|
+
/** Drop the URL prefix for the default locale (`/`, `/fr/…`). Defaults to `true`. */
|
|
591
|
+
hideDefaultLocalePrefix?: boolean;
|
|
592
|
+
/** Every locale the site ships (at least one). */
|
|
593
|
+
locales: LocaleConfigInput[];
|
|
594
|
+
/** `dir`: locale directories (`fr/page.mdx`). `dot`: filename suffix (`page.fr.mdx`). */
|
|
595
|
+
parser?: "dir" | "dot";
|
|
596
|
+
/**
|
|
597
|
+
* Per-locale UI string overrides, e.g.
|
|
598
|
+
* `{ fr: { search: { button: "Rechercher" } } }`.
|
|
599
|
+
*/
|
|
600
|
+
ui?: Record<string, Record<string, Record<string, string>>>;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// ---------------------------------------------------------------------------
|
|
604
|
+
// Deployment & redirects
|
|
605
|
+
// ---------------------------------------------------------------------------
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Where and how the site deploys. `site` (and `adapter`) are auto-detected from
|
|
609
|
+
* the platform env on Vercel, Netlify, and Cloudflare.
|
|
610
|
+
*/
|
|
611
|
+
export interface DeploymentConfig {
|
|
612
|
+
/** Astro adapter for server output. `null` (default) keeps a static build. */
|
|
613
|
+
adapter?: "vercel" | "node" | "netlify" | "cloudflare" | null;
|
|
614
|
+
/** Base path when the site is served from a subdirectory. */
|
|
615
|
+
base?: string;
|
|
616
|
+
/** Build output mode. Defaults to `static`. */
|
|
617
|
+
output?: "static" | "server";
|
|
618
|
+
/**
|
|
619
|
+
* Canonical site URL. Needed for absolute links, the sitemap, and OG images;
|
|
620
|
+
* auto-detected on supported platforms.
|
|
621
|
+
*/
|
|
622
|
+
site?: string;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/** A URL redirect rule. */
|
|
626
|
+
export interface RedirectConfig {
|
|
627
|
+
/** Path to redirect from. */
|
|
628
|
+
from: string;
|
|
629
|
+
/** HTTP status. Defaults to `301`. */
|
|
630
|
+
status?: 301 | 302 | 307 | 308;
|
|
631
|
+
/** Path or URL to redirect to. */
|
|
632
|
+
to: string;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// ---------------------------------------------------------------------------
|
|
636
|
+
// SEO
|
|
637
|
+
// ---------------------------------------------------------------------------
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* robots.txt `Content-Signal` preferences. `true` (default) declares the docs
|
|
641
|
+
* open to search and agents; `false` opts out entirely; an object restricts
|
|
642
|
+
* individual signals (unset signals stay allowed).
|
|
643
|
+
*/
|
|
644
|
+
export type ContentSignalsConfig =
|
|
645
|
+
| boolean
|
|
646
|
+
| {
|
|
647
|
+
/** Allow grounding / RAG use at answer time (`ai-input`). Defaults to `true`. */
|
|
648
|
+
aiInput?: boolean;
|
|
649
|
+
/** Allow model training (`ai-train`). Defaults to `true`. */
|
|
650
|
+
aiTrain?: boolean;
|
|
651
|
+
/** Allow traditional and AI search indexing (`search`). Defaults to `true`. */
|
|
652
|
+
search?: boolean;
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
/** RSS/Atom feed generation. */
|
|
656
|
+
export interface RssConfig {
|
|
657
|
+
/** Generate feeds. Defaults to `true`. */
|
|
658
|
+
enabled?: boolean;
|
|
659
|
+
/** Max items per feed, newest first. Defaults to `50`. */
|
|
660
|
+
limit?: number;
|
|
661
|
+
/** Content types that each get a feed at `/<type>/rss.xml`. Defaults to blog + changelog. */
|
|
662
|
+
types?: string[];
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/** Discoverability: OG images, feeds, sitemap, robots, and structured data. */
|
|
666
|
+
export interface SeoConfig {
|
|
667
|
+
/**
|
|
668
|
+
* Emit `agent-readability.json`: a manifest indexing the agent-facing surface
|
|
669
|
+
* (llms.txt, Markdown mirrors, MCP, feeds). Defaults to `true`.
|
|
670
|
+
*/
|
|
671
|
+
agentReadability?: boolean;
|
|
672
|
+
/** robots.txt `Content-Signal` usage declaration. Defaults to `true`. */
|
|
673
|
+
contentSignals?: ContentSignalsConfig;
|
|
674
|
+
/** Per-page Open Graph image generation. */
|
|
675
|
+
og?: {
|
|
676
|
+
/**
|
|
677
|
+
* Generate an OG image per page. Defaults to on once a deployment `site`
|
|
678
|
+
* URL is known and off otherwise (`og:image` must be absolute). An explicit
|
|
679
|
+
* value always wins.
|
|
680
|
+
*/
|
|
681
|
+
enabled?: boolean;
|
|
682
|
+
};
|
|
683
|
+
/** Generate robots.txt (with a Sitemap reference when available). Defaults to `true`. */
|
|
684
|
+
robots?: boolean;
|
|
685
|
+
/** RSS/Atom feeds. */
|
|
686
|
+
rss?: RssConfig;
|
|
687
|
+
/** Generate sitemap.xml (requires `deployment.site`). Defaults to `true`. */
|
|
688
|
+
sitemap?: boolean;
|
|
689
|
+
/** Emit schema.org JSON-LD in each page's `<head>`. Defaults to `true`. */
|
|
690
|
+
structuredData?: boolean;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// ---------------------------------------------------------------------------
|
|
694
|
+
// GitHub
|
|
695
|
+
// ---------------------------------------------------------------------------
|
|
696
|
+
|
|
697
|
+
/** Source repository, powering "Edit this page" links and the header repo link. */
|
|
698
|
+
export interface GithubConfig {
|
|
699
|
+
/** Default branch. Defaults to `main`. */
|
|
700
|
+
branch?: string;
|
|
701
|
+
/** Path from the repo root to the project root (for monorepos). */
|
|
702
|
+
dir?: string;
|
|
703
|
+
/** Repository owner (user or org). */
|
|
704
|
+
owner: string;
|
|
705
|
+
/** Repository name. */
|
|
706
|
+
repo: string;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// ---------------------------------------------------------------------------
|
|
710
|
+
// Markdown
|
|
711
|
+
// ---------------------------------------------------------------------------
|
|
712
|
+
|
|
713
|
+
/** Code-block rendering options. */
|
|
714
|
+
export interface CodeConfig {
|
|
715
|
+
/** Show a brand language icon in the code-block header. Defaults to `true`. */
|
|
716
|
+
icons?: boolean;
|
|
717
|
+
/** Wrap long lines instead of scrolling horizontally. Defaults to `false`. */
|
|
718
|
+
wrap?: boolean;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/** Markdown / MDX rendering behavior. */
|
|
722
|
+
export interface MarkdownConfig {
|
|
723
|
+
/** Code-block rendering: language icons, line wrap. */
|
|
724
|
+
code?: CodeConfig;
|
|
725
|
+
/** Syntax-highlighting themes for fenced code blocks. */
|
|
726
|
+
codeBlocks?: {
|
|
727
|
+
/** Shiki theme names per color mode. */
|
|
728
|
+
theme?: {
|
|
729
|
+
/** Dark-mode theme. Defaults to `github-dark`. */
|
|
730
|
+
dark?: string;
|
|
731
|
+
/** Light-mode theme. Defaults to `github-light`. */
|
|
732
|
+
light?: string;
|
|
733
|
+
};
|
|
734
|
+
};
|
|
735
|
+
/**
|
|
736
|
+
* Wrap each `##`–`######` heading in a self-anchor link so readers can copy,
|
|
737
|
+
* bookmark, or share a section permalink. Defaults to `true`.
|
|
738
|
+
*/
|
|
739
|
+
headingAnchors?: boolean;
|
|
740
|
+
/** Make content images click-to-zoom (lightbox). Defaults to `true`. */
|
|
741
|
+
imageZoom?: boolean;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// ---------------------------------------------------------------------------
|
|
745
|
+
// OpenAPI / AsyncAPI
|
|
746
|
+
// ---------------------------------------------------------------------------
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* OpenAPI reference. By default (`renderer: "blume"`) Blume renders its own UI:
|
|
750
|
+
* one real page per operation, grouped by tag in the sidebar and included in
|
|
751
|
+
* search, llms.txt, and OG. Set `renderer: "scalar"` for the embedded Scalar
|
|
752
|
+
* SPA (a single self-contained route).
|
|
753
|
+
*/
|
|
754
|
+
export interface OpenApiConfig {
|
|
755
|
+
/** Code-sample languages shown per operation (Blume renderer). */
|
|
756
|
+
codeSamples?: string[];
|
|
757
|
+
/** Turn the reference on. Defaults to `false`. */
|
|
758
|
+
enabled?: boolean;
|
|
759
|
+
/** Start nested schema rows expanded (Blume renderer). Defaults to `false`. */
|
|
760
|
+
expandSchemas?: boolean;
|
|
761
|
+
/** Who renders the reference. Defaults to `blume`. */
|
|
762
|
+
renderer?: "blume" | "scalar";
|
|
763
|
+
/** Where the reference mounts. Defaults to `/reference`. */
|
|
764
|
+
route?: string;
|
|
765
|
+
/** One or more specs; each renders on its own route by default. */
|
|
766
|
+
sources?: OpenApiSource[];
|
|
767
|
+
/** Shorthand for a single source: `sources: [{ spec }]`. */
|
|
768
|
+
spec?: string;
|
|
769
|
+
/** Scalar theme name (Scalar renderer only). */
|
|
770
|
+
theme?: string;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* AsyncAPI reference, rendered via the embedded Scalar SPA (which auto-detects
|
|
775
|
+
* the document type). Same shape as {@link OpenApiConfig}; only the default
|
|
776
|
+
* `route` differs.
|
|
777
|
+
*/
|
|
778
|
+
export interface AsyncApiConfig {
|
|
779
|
+
/** Turn the reference on. Defaults to `false`. */
|
|
780
|
+
enabled?: boolean;
|
|
781
|
+
/** Where the reference mounts. Defaults to `/events`. */
|
|
782
|
+
route?: string;
|
|
783
|
+
/** One or more specs. */
|
|
784
|
+
sources?: OpenApiSource[];
|
|
785
|
+
/** Shorthand for a single source. */
|
|
786
|
+
spec?: string;
|
|
787
|
+
/** Scalar theme name. */
|
|
788
|
+
theme?: string;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// ---------------------------------------------------------------------------
|
|
792
|
+
// Misc top-level unions
|
|
793
|
+
// ---------------------------------------------------------------------------
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Reader-facing "Export" page actions. A boolean toggles both formats; the
|
|
797
|
+
* object form enables each individually. Defaults to `false`.
|
|
798
|
+
*/
|
|
799
|
+
export type ExportConfig =
|
|
800
|
+
| boolean
|
|
801
|
+
| {
|
|
802
|
+
/** Offer EPUB export (client-side). Defaults to `false`. */
|
|
803
|
+
epub?: boolean;
|
|
804
|
+
/** Offer PDF export (via print). Defaults to `false`. */
|
|
805
|
+
pdf?: boolean;
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* "Last updated" timestamps. `false` (default) disables them; `true` derives
|
|
810
|
+
* each date from git history; the object form selects the source. A page's
|
|
811
|
+
* `lastModified` frontmatter always wins.
|
|
812
|
+
*/
|
|
813
|
+
export type LastModifiedConfig =
|
|
814
|
+
| boolean
|
|
815
|
+
| {
|
|
816
|
+
/** Where the date comes from. Defaults to `git`. */
|
|
817
|
+
type?: "git" | "frontmatter";
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* On-page table of contents. `true`/`false` toggles it; the object form narrows
|
|
822
|
+
* the heading range. Defaults to on, H2–H3.
|
|
823
|
+
*/
|
|
824
|
+
export type TocConfig =
|
|
825
|
+
| boolean
|
|
826
|
+
| {
|
|
827
|
+
/** Deepest heading level to include (1–6). Defaults to `3`. */
|
|
828
|
+
maxHeadingLevel?: number;
|
|
829
|
+
/** Shallowest heading level to include (1–6). Defaults to `2`. */
|
|
830
|
+
minHeadingLevel?: number;
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
// ---------------------------------------------------------------------------
|
|
834
|
+
// The top-level config
|
|
835
|
+
// ---------------------------------------------------------------------------
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* A Blume site's configuration — the object passed to {@link defineConfig} in
|
|
839
|
+
* `blume.config.ts`. Every field is optional; an empty config renders the
|
|
840
|
+
* Markdown/MDX under `docs/` with sensible defaults.
|
|
841
|
+
*/
|
|
842
|
+
export interface BlumeConfig {
|
|
843
|
+
/** AI-facing features: the Ask AI assistant and an `llms.txt` manifest. */
|
|
844
|
+
ai?: AiConfig;
|
|
845
|
+
/** Analytics providers (PostHog, Vercel, or arbitrary scripts). */
|
|
846
|
+
analytics?: AnalyticsConfig;
|
|
847
|
+
/** AsyncAPI reference (embedded Scalar renderer). */
|
|
848
|
+
asyncapi?: AsyncApiConfig;
|
|
849
|
+
/** Site-wide announcement banner shown above the header. */
|
|
850
|
+
banner?: BannerConfig;
|
|
851
|
+
/** Where content lives and how it's discovered. */
|
|
852
|
+
content?: ContentConfig;
|
|
853
|
+
/** Where and how the site deploys (site URL, adapter, output mode). */
|
|
854
|
+
deployment?: DeploymentConfig;
|
|
855
|
+
/** Default meta description, used where a page sets none. */
|
|
856
|
+
description?: string;
|
|
857
|
+
/**
|
|
858
|
+
* Where `<Component path>` resolves live previews and their source from,
|
|
859
|
+
* relative to the project root. Defaults to `examples`. May be a glob to
|
|
860
|
+
* target a registry that colocates component sources with their examples.
|
|
861
|
+
*/
|
|
862
|
+
examples?: string;
|
|
863
|
+
/** Reader-facing PDF/EPUB export actions. Defaults to `false`. */
|
|
864
|
+
export?: ExportConfig;
|
|
865
|
+
/** Show the per-page "Was this helpful?" widget. Defaults to `true`. */
|
|
866
|
+
feedback?: boolean;
|
|
867
|
+
/** Source repository (Edit-this-page links and the header repo link). */
|
|
868
|
+
github?: GithubConfig;
|
|
869
|
+
/** Internationalization (opt-in multi-locale). */
|
|
870
|
+
i18n?: I18nConfig;
|
|
871
|
+
/** "Last updated" timestamps from git history or frontmatter. Defaults to `false`. */
|
|
872
|
+
lastModified?: LastModifiedConfig;
|
|
873
|
+
/** Site logo / brand mark. */
|
|
874
|
+
logo?: LogoConfig;
|
|
875
|
+
/** Markdown / MDX rendering behavior. */
|
|
876
|
+
markdown?: MarkdownConfig;
|
|
877
|
+
/** Expose the docs as an MCP server for agents. */
|
|
878
|
+
mcp?: McpConfig;
|
|
879
|
+
/** Header, sidebar, tabs, and switchers. */
|
|
880
|
+
navigation?: NavigationConfig;
|
|
881
|
+
/** Native OpenAPI reference. */
|
|
882
|
+
openapi?: OpenApiConfig;
|
|
883
|
+
/** URL redirect rules. */
|
|
884
|
+
redirects?: RedirectConfig[];
|
|
885
|
+
/** Search backend and credentials. */
|
|
886
|
+
search?: SearchConfig;
|
|
887
|
+
/** Discoverability: OG images, feeds, sitemap, robots, structured data. */
|
|
888
|
+
seo?: SeoConfig;
|
|
889
|
+
/** Colors, fonts, radius, and color-mode behavior. */
|
|
890
|
+
theme?: ThemeConfig;
|
|
891
|
+
/** Site title, shown in the header, `<title>`, and OG images. Defaults to `Documentation`. */
|
|
892
|
+
title?: string;
|
|
893
|
+
/** On-page table of contents. Defaults to on (H2–H3). */
|
|
894
|
+
toc?: TocConfig;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// ---------------------------------------------------------------------------
|
|
898
|
+
// Drift guard
|
|
899
|
+
// ---------------------------------------------------------------------------
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* Compile-time check that {@link BlumeConfig} stays structurally in sync with
|
|
903
|
+
* the input side of {@link blumeConfigSchema}. If a schema field is added,
|
|
904
|
+
* removed, renamed, retyped, or has its optionality changed, one of these
|
|
905
|
+
* assertions stops compiling and this documented interface must be updated to
|
|
906
|
+
* match. (Newly-added *nested optional* fields aren't caught by assignability
|
|
907
|
+
* alone — the top-level key check below covers the common case; keep an eye on
|
|
908
|
+
* nested additions.)
|
|
909
|
+
*/
|
|
910
|
+
type SchemaInput = z.input<typeof blumeConfigSchema>;
|
|
911
|
+
|
|
912
|
+
type AssertExtends<A extends B, B> = A;
|
|
913
|
+
|
|
914
|
+
// Every value accepted by `defineConfig` is a valid schema input.
|
|
915
|
+
type _ConfigIsValidInput = AssertExtends<BlumeConfig, SchemaInput>;
|
|
916
|
+
// Every value the schema accepts is expressible via the documented interface.
|
|
917
|
+
type _InputMatchesConfig = AssertExtends<SchemaInput, BlumeConfig>;
|
|
918
|
+
// Top-level key sets are identical (catches added/removed keys, even optional).
|
|
919
|
+
type _NoExtraOrMissingKeys = AssertExtends<
|
|
920
|
+
| Exclude<keyof BlumeConfig, keyof SchemaInput>
|
|
921
|
+
| Exclude<keyof SchemaInput, keyof BlumeConfig>,
|
|
922
|
+
never
|
|
923
|
+
>;
|