blume 1.0.4 → 1.1.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.
- package/CHANGELOG.md +65 -0
- package/dist/cli/index.js +13255 -10232
- package/dist/cli/index.js.map +91 -60
- package/dist/types/core/config-input.d.ts +61 -1
- package/dist/types/core/data.d.ts +9 -0
- package/dist/types/core/deployment-env.d.ts +6 -0
- package/dist/types/core/diagnostics.d.ts +23 -0
- package/dist/types/core/i18n-ui.d.ts +8 -8
- package/dist/types/core/schema.d.ts +131 -22
- package/dist/types/core/sources/types.d.ts +3 -1
- package/dist/types/core/standard-schema.d.ts +41 -0
- package/dist/types/core/types.d.ts +13 -0
- package/dist/types/og/card.d.ts +63 -0
- package/dist/types/og/dimensions.d.ts +12 -0
- package/docs/01-quickstart.mdx +1 -1
- package/docs/02-deployment.mdx +9 -1
- package/docs/advanced/api-reference.mdx +11 -0
- package/docs/advanced/changelog.mdx +1 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/configuration/ai.mdx +1 -1
- package/docs/configuration/customization.mdx +1 -1
- package/docs/configuration/export.mdx +1 -1
- package/docs/configuration/index.mdx +21 -1
- package/docs/configuration/search.mdx +28 -1
- package/docs/configuration/seo.mdx +21 -2
- package/docs/configuration/theming.mdx +1 -1
- package/docs/content/components.mdx +14 -0
- package/docs/content/index.mdx +1 -1
- package/docs/content/meta.mdx +1 -1
- package/docs/content/navigation.mdx +1 -1
- package/docs/content/sources.mdx +1 -1
- package/docs/reference/cli.mdx +79 -1
- package/docs/reference/frontmatter.mdx +29 -1
- package/package.json +3 -3
- package/skills/blume-migrate/SKILL.md +1 -1
- package/skills/blume-migrate/references/mintlify.md +3 -2
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +16 -4
- package/src/ai/llms.ts +15 -0
- package/src/astro/adapter-root.ts +70 -0
- package/src/astro/generate.ts +50 -19
- package/src/astro/index.ts +1 -0
- package/src/astro/pages.ts +18 -3
- package/src/astro/templates.ts +65 -22
- package/src/audit/agent.ts +114 -0
- package/src/audit/catalog.ts +826 -0
- package/src/audit/checks/assets.ts +177 -0
- package/src/audit/checks/content.ts +231 -0
- package/src/audit/checks/duplicates.ts +131 -0
- package/src/audit/checks/i18n.ts +246 -0
- package/src/audit/checks/indexability.ts +213 -0
- package/src/audit/checks/links.ts +223 -0
- package/src/audit/checks/llms.ts +135 -0
- package/src/audit/checks/network.ts +272 -0
- package/src/audit/checks/og-image.ts +113 -0
- package/src/audit/checks/redirects.ts +87 -0
- package/src/audit/checks/robots.ts +114 -0
- package/src/audit/checks/sitemap.ts +229 -0
- package/src/audit/checks/social.ts +238 -0
- package/src/audit/crawl.ts +259 -0
- package/src/audit/graph.ts +74 -0
- package/src/audit/html.ts +54 -0
- package/src/audit/image-size.ts +63 -0
- package/src/audit/locate.ts +33 -0
- package/src/audit/redirects.ts +74 -0
- package/src/audit/report.ts +278 -0
- package/src/audit/run.ts +198 -0
- package/src/audit/snapshot.ts +189 -0
- package/src/audit/types.ts +214 -0
- package/src/audit/url.ts +103 -0
- package/src/cli/commands/audit.ts +205 -0
- package/src/cli/commands/build.ts +51 -12
- package/src/cli/index.ts +2 -0
- package/src/components/content/Tabs.astro +98 -15
- package/src/components/layout/Breadcrumbs.astro +1 -1
- package/src/components/layout/Header.astro +1 -0
- package/src/components/layout/PageFeedback.astro +1 -1
- package/src/components/layout/PageLayout.astro +5 -1
- package/src/components/layout/Pagination.astro +1 -1
- package/src/components/layout/RootLayout.astro +5 -3
- package/src/components/layout/Search.astro +35 -6
- package/src/components/layout/TableOfContents.astro +1 -1
- package/src/components/openapi/Authorization.astro +80 -0
- package/src/components/openapi/Operation.astro +19 -1
- package/src/components/openapi/ParametersTable.astro +1 -1
- package/src/components/openapi/security.ts +201 -0
- package/src/components/openapi/snippets.ts +42 -13
- package/src/core/config-input.ts +66 -1
- package/src/core/data.ts +9 -1
- package/src/core/deployment-env.ts +9 -0
- package/src/core/diagnostics.ts +59 -12
- package/src/core/links.ts +2 -91
- package/src/core/nav-diagnostics.ts +48 -4
- package/src/core/probe.ts +136 -0
- package/src/core/project-graph.ts +8 -0
- package/src/core/schema.ts +86 -3
- package/src/core/sources/normalize.ts +198 -25
- package/src/core/sources/types.ts +3 -1
- package/src/core/standard-schema.ts +54 -0
- package/src/core/types.ts +13 -0
- package/src/deploy/adapter-output.ts +27 -15
- package/src/deploy/headers.ts +66 -0
- package/src/deploy/redirects.ts +49 -9
- package/src/og/card.ts +98 -33
- package/src/og/index.ts +1 -1
- package/src/search/popular.ts +33 -0
- package/src/theme/entry.ts +6 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Standard Schema interface (https://standardschema.dev), the minimal
|
|
3
|
+
* `~standard` surface shared by Zod 3.24+, Zod 4, Valibot, ArkType, and
|
|
4
|
+
* friends. Blume accepts user-supplied validation schemas (e.g.
|
|
5
|
+
* `frontmatter.extend`) through this interface instead of Zod's own types:
|
|
6
|
+
* `blume.config.ts` imports zod from the *consumer's* node_modules, which may
|
|
7
|
+
* be a different major version than the zod Blume bundles, and calling Zod
|
|
8
|
+
* methods (`.extend()`, `.safeParse()`) across instances is unsupported. The
|
|
9
|
+
* `~standard.validate` contract is version- and library-agnostic.
|
|
10
|
+
*/
|
|
11
|
+
/** One validation failure, with an optional path into the checked value. */
|
|
12
|
+
export interface StandardSchemaIssue {
|
|
13
|
+
readonly message: string;
|
|
14
|
+
readonly path?: readonly (PropertyKey | {
|
|
15
|
+
readonly key: PropertyKey;
|
|
16
|
+
})[] | undefined;
|
|
17
|
+
}
|
|
18
|
+
/** A passing validation: the (possibly transformed) output value. */
|
|
19
|
+
export interface StandardSchemaSuccess<Output> {
|
|
20
|
+
readonly value: Output;
|
|
21
|
+
readonly issues?: undefined;
|
|
22
|
+
}
|
|
23
|
+
/** A failing validation: one or more issues. */
|
|
24
|
+
export interface StandardSchemaFailure {
|
|
25
|
+
readonly issues: readonly StandardSchemaIssue[];
|
|
26
|
+
}
|
|
27
|
+
export type StandardSchemaResult<Output> = StandardSchemaSuccess<Output> | StandardSchemaFailure;
|
|
28
|
+
/** A validation schema exposing the Standard Schema `~standard` contract. */
|
|
29
|
+
export interface StandardSchema<Input = unknown, Output = Input> {
|
|
30
|
+
readonly "~standard": {
|
|
31
|
+
readonly version: 1;
|
|
32
|
+
readonly vendor: string;
|
|
33
|
+
readonly validate: (value: unknown) => StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>;
|
|
34
|
+
readonly types?: {
|
|
35
|
+
readonly input: Input;
|
|
36
|
+
readonly output: Output;
|
|
37
|
+
} | undefined;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Whether a config-supplied value implements the `~standard` contract. */
|
|
41
|
+
export declare const isStandardSchema: (value: unknown) => value is StandardSchema;
|
|
@@ -12,6 +12,13 @@ export interface Diagnostic {
|
|
|
12
12
|
file?: string;
|
|
13
13
|
line?: number;
|
|
14
14
|
column?: number;
|
|
15
|
+
/**
|
|
16
|
+
* The built URL this diagnostic is about, for findings that are a property of
|
|
17
|
+
* the output rather than of a source file (`blume audit`). Set alongside
|
|
18
|
+
* `file`/`line` where the page maps back to authored content, so a finding can
|
|
19
|
+
* name both the URL that's wrong and the frontmatter line that fixes it.
|
|
20
|
+
*/
|
|
21
|
+
url?: string;
|
|
15
22
|
schemaPath?: string;
|
|
16
23
|
suggestion?: string;
|
|
17
24
|
docsUrl?: string;
|
|
@@ -110,6 +117,12 @@ export interface PageRecord {
|
|
|
110
117
|
description?: string;
|
|
111
118
|
contentType: string;
|
|
112
119
|
meta: PageMeta;
|
|
120
|
+
/**
|
|
121
|
+
* Custom frontmatter values declared via `frontmatter.extend`, validated by
|
|
122
|
+
* the user-supplied schemas (schema output, so transforms apply). Present
|
|
123
|
+
* only when the project opts in and the page carries at least one value.
|
|
124
|
+
*/
|
|
125
|
+
custom?: Record<string, unknown>;
|
|
113
126
|
headings: Heading[];
|
|
114
127
|
/** Whether the file is `.md`/`.mdx`. */
|
|
115
128
|
format: "md" | "mdx";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { RenderOptions } from "takumi-js";
|
|
2
|
+
/**
|
|
3
|
+
* A Google Font family to load into the OG card renderer. A bare string is the
|
|
4
|
+
* family name (weight 400, normal style); the object form pins weight and style.
|
|
5
|
+
* Handed straight to Takumi's `googleFonts` helper, which fetches the family
|
|
6
|
+
* from Google Fonts at build and returns per-glyph coverage subsets.
|
|
7
|
+
*/
|
|
8
|
+
export type OgFont = string | {
|
|
9
|
+
/** Google Fonts family name, e.g. `"Noto Sans JP"`. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** `400`, `[400, 700]`, or a variable range like `"100..900"`. */
|
|
12
|
+
weight?: number | number[] | string;
|
|
13
|
+
/** `"normal"`, `"italic"`, or both. */
|
|
14
|
+
style?: "normal" | "italic" | ("normal" | "italic")[];
|
|
15
|
+
};
|
|
16
|
+
export interface OgCardPalette {
|
|
17
|
+
accent?: string;
|
|
18
|
+
background?: string;
|
|
19
|
+
border?: string;
|
|
20
|
+
foreground?: string;
|
|
21
|
+
muted?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface OgCardOptions {
|
|
24
|
+
/** Large headline — the page title. */
|
|
25
|
+
title: string;
|
|
26
|
+
/** Accent color (named preset or any CSS color) for the fallback brand mark. */
|
|
27
|
+
accent?: string;
|
|
28
|
+
/** Brand/site name shown in the top-left lockup. */
|
|
29
|
+
brand?: string;
|
|
30
|
+
/** Muted subtitle under the headline (usually the site description). */
|
|
31
|
+
description?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Inlined SVG markup of the configured logo, painted into
|
|
34
|
+
* the brand lockup. Falls back to an accent mark when absent.
|
|
35
|
+
*/
|
|
36
|
+
logo?: string;
|
|
37
|
+
/** Optional colors for the generated card. */
|
|
38
|
+
palette?: OgCardPalette;
|
|
39
|
+
/** Footer-left repository slug, e.g. `owner/repo`. */
|
|
40
|
+
repo?: string;
|
|
41
|
+
/** Footer-right site host, e.g. `docs.acme.com`. */
|
|
42
|
+
site?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Pre-fetched image entries, or a group controlling how remote images (and
|
|
45
|
+
* emoji glyphs) are fetched. Blume merges in a shared glyph cache; see
|
|
46
|
+
* {@link resolveImages}.
|
|
47
|
+
*/
|
|
48
|
+
images?: RenderOptions["images"];
|
|
49
|
+
/**
|
|
50
|
+
* Google Font families for non-Latin titles. Takumi's built-in font covers
|
|
51
|
+
* only Latin, so a CJK (etc.) title renders as tofu without a family that
|
|
52
|
+
* covers its script — see {@link loadFonts}.
|
|
53
|
+
*/
|
|
54
|
+
fonts?: OgFont[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Truncate to `max` code points with an ellipsis. Slices by code points, not
|
|
58
|
+
* UTF-16 units, so cutting mid-emoji doesn't leave a lone surrogate (a broken
|
|
59
|
+
* glyph) before the ellipsis.
|
|
60
|
+
*/
|
|
61
|
+
export declare const truncate: (value: string, max: number) => string;
|
|
62
|
+
/** Render a 1200x630 Open Graph card to a PNG buffer. */
|
|
63
|
+
export declare const renderOgImage: (options: OgCardOptions) => Promise<Uint8Array>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dimensions of a generated OG card, shared by the renderer (`card.ts`) and the
|
|
3
|
+
* layouts that declare them as `og:image:width`/`og:image:height` so a crawler
|
|
4
|
+
* can lay out the card without fetching the PNG first.
|
|
5
|
+
*
|
|
6
|
+
* This lives apart from `card.ts` because that module imports the Takumi native
|
|
7
|
+
* binding at load; a layout importing it would drag the renderer into every
|
|
8
|
+
* page render (and into the prerender/SSR bundles that externalize it).
|
|
9
|
+
*/
|
|
10
|
+
export declare const OG_IMAGE_WIDTH = 1200;
|
|
11
|
+
export declare const OG_IMAGE_HEIGHT = 630;
|
|
12
|
+
export declare const OG_IMAGE_TYPE = "image/png";
|
package/docs/01-quickstart.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Quickstart
|
|
3
|
-
description: Install Blume, scaffold a project, and ship your first page in minutes.
|
|
3
|
+
description: Install Blume, scaffold a new project, and ship your first documentation page in minutes — then grow it into a full site at your own pace.
|
|
4
4
|
sidebar:
|
|
5
5
|
label: Quickstart
|
|
6
6
|
order: 1
|
package/docs/02-deployment.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Deployment
|
|
3
|
-
description: Deploy static docs to any host, or switch to server rendering with an adapter.
|
|
3
|
+
description: Deploy static docs to any host with zero configuration, or switch to server-side rendering with an adapter when you need dynamic behavior.
|
|
4
4
|
sidebar:
|
|
5
5
|
label: Deployment
|
|
6
6
|
order: 2
|
|
@@ -119,6 +119,14 @@ redirects: [{ from: "/old", to: "/new", status: 301 }];
|
|
|
119
119
|
`from` is matched as an exact path — wildcards and pattern matching (e.g. `/blog/:slug` or `/old/*`) aren't supported. If you need pattern-based rules, handle them in an infrastructure file like `vercel.json` (which supports wildcard `source` patterns) or your host's redirect config instead. A `vercel.json` you ship in `public/` is preserved as-is.
|
|
120
120
|
:::
|
|
121
121
|
|
|
122
|
+
:::note
|
|
123
|
+
Write both `from` and `to` as if mounted at root — under [`deployment.base`](#subpath-deploys) and [`basePath`](#mount-the-docs-under-a-path) alike, Blume rewrites both sides for you, so a redirect lands inside the base. A base you've already written into `to` by hand is preserved rather than doubled.
|
|
124
|
+
:::
|
|
125
|
+
|
|
126
|
+
## Content types
|
|
127
|
+
|
|
128
|
+
A static build also emits a `_headers` file that pins `charset=utf-8` onto the raw AI-ready endpoints — `/<route>.md`, `/<route>.mdx`, and the `.txt` files (`llms.txt`, `llms-full.txt`). Those responses are valid UTF-8, but many static hosts serve them as `text/markdown` / `text/plain` with **no** charset, and browsers then fall back to Windows-1252 — so non-ASCII docs (Japanese, accented Latin, …) render as mojibake when the raw URL is opened directly. HTML pages are unaffected because they carry `<meta charset>`. Netlify and Cloudflare (Pages/Workers static assets) read `_headers`; hosts that don't (Vercel, S3) ignore the file harmlessly. A `_headers` you ship in `public/` is left untouched.
|
|
129
|
+
|
|
122
130
|
## Environment variables
|
|
123
131
|
|
|
124
132
|
When a feature needs a runtime secret, Blume warns at `blume dev`/`build` if it's missing — so the problem surfaces early instead of at the first request:
|
|
@@ -78,6 +78,17 @@ openapi: {
|
|
|
78
78
|
|
|
79
79
|
`spec` is shorthand for a single-entry `sources`, so you only reach for `sources` when you have more than one.
|
|
80
80
|
|
|
81
|
+
## Authorization
|
|
82
|
+
|
|
83
|
+
Operations that declare [security requirements](https://spec.openapis.org/oas/v3.1.0#security-requirement-object) render an **Authorization** section above their parameters, and the generated code samples send a placeholder credential (`Authorization: Bearer YOUR_TOKEN`, an API-key header, or a query key — whatever the scheme calls for). There's nothing to configure: Blume reads `security` from the spec, so the reference always matches what the API actually enforces.
|
|
84
|
+
|
|
85
|
+
The OpenAPI semantics carry over as written:
|
|
86
|
+
|
|
87
|
+
- An operation's own `security` overrides the document's root default; `security: []` marks it **public** and renders no Authorization section.
|
|
88
|
+
- Multiple requirement entries are alternatives — rendered as "or" groups; every scheme inside one entry is required together. The first alternative feeds the code samples.
|
|
89
|
+
- An empty `{}` entry means auth is **optional** for that operation, and the section says so.
|
|
90
|
+
- OAuth2 scopes are listed per scheme; scheme `description`s from `components.securitySchemes` render inline.
|
|
91
|
+
|
|
81
92
|
## The Scalar renderer
|
|
82
93
|
|
|
83
94
|
The native renderer is the default. If you'd rather embed [Scalar](https://scalar.com)'s self-contained API reference — its own sidebar, search, theme, and "Try it" playground on a single route — set `renderer: "scalar"`:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Changelog
|
|
3
|
-
description: Author release notes as content, and Blume builds a timeline page and an RSS feed automatically.
|
|
3
|
+
description: Author release notes as ordinary content files or source them from GitHub Releases, and Blume builds a timeline page and an RSS feed automatically.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Blume ships a changelog out of the box. Write each release as a normal content file, mark it `type: changelog`, and Blume collects every entry into a generated timeline page and an RSS feed — no layout to build, no list to maintain. Or skip the files entirely and [source your changelog from GitHub Releases](#from-github-releases).
|
package/docs/advanced/skills.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Skills
|
|
3
|
-
description: The agent skills Blume ships — playbooks that teach a coding agent to build and maintain a Blume docs site.
|
|
3
|
+
description: The agent skills Blume ships — playbooks that teach a coding agent like Claude Code, Codex, or Cursor to build and maintain a Blume docs site.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Blume ships [agent skills](https://docs.claude.com/en/docs/claude-code/skills) — playbooks that teach a coding agent (Claude Code, Codex, Cursor) how to do a Blume-shaped job without you explaining it. They live on GitHub in the repo's `skills/` folder and are bundled in the package at `node_modules/blume/skills/` once Blume is installed, so any agent can be pointed at a `SKILL.md` directly.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: AI
|
|
3
|
-
description:
|
|
3
|
+
description: Make your docs machine-readable with llms.txt, add an optional in-page Ask AI assistant, and expose a hosted MCP server for coding agents.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Blume has a few AI features: machine-readable docs for external tools (`llms.txt`, on by default), an in-page **Ask AI** assistant, and a hosted **MCP server** for coding agents. Ask AI and MCP are opt-in, and static docs stay fully static until you turn a feature on.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Customization
|
|
3
|
-
description: Override components, add interactive islands, mount custom pages, install registry components, or eject.
|
|
3
|
+
description: Override components, add interactive islands, mount custom pages, install registry components, or eject entirely when you need full control.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## Component overrides
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Export
|
|
3
|
-
description: Let readers download any page as a PDF or EPUB — client-side, so static builds stay static.
|
|
3
|
+
description: Let readers download any page as a PDF or EPUB — rendered client-side, so your static builds stay static and need no server infrastructure.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Blume can add an **Export** action to the [page actions](/docs/content/navigation#page-actions) beneath the table of contents, letting readers save the page they're on as a **PDF** or an **EPUB**. It's off by default and entirely client-side — no server, and [static](/docs/deployment) builds stay static.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Configuration file
|
|
3
|
-
description: Every option in blume.config.ts
|
|
3
|
+
description: Every option in blume.config.ts, from site metadata and content sources to the links that lead into each individual feature configuration guide.
|
|
4
4
|
sidebar:
|
|
5
5
|
label: blume.config.ts
|
|
6
6
|
---
|
|
@@ -188,6 +188,26 @@ content: {
|
|
|
188
188
|
|
|
189
189
|
Static assets live in `public/` — a file at `public/logo.png` is served at `/logo.png`, so a reference like `` resolves against `public/images/create.png`.
|
|
190
190
|
|
|
191
|
+
## Frontmatter
|
|
192
|
+
|
|
193
|
+
Page frontmatter is strictly validated — an unknown key fails the build, so typos are caught early. To carry project-specific metadata (an owner, a review date), declare the extra keys under `frontmatter.extend`, each mapped to a schema you supply:
|
|
194
|
+
|
|
195
|
+
```ts blume.config.ts lineNumbers
|
|
196
|
+
import { defineConfig } from "blume";
|
|
197
|
+
import { z } from "zod";
|
|
198
|
+
|
|
199
|
+
export default defineConfig({
|
|
200
|
+
frontmatter: {
|
|
201
|
+
extend: {
|
|
202
|
+
owner: z.string(),
|
|
203
|
+
reviewedAt: z.coerce.date().optional(),
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Any [Standard Schema](https://standardschema.dev) library works — Zod (whichever version your project installs), Valibot, ArkType. Keys outside the extension stay strictly validated, so typo-catching is unchanged. See [Custom keys](/docs/reference/frontmatter#custom-keys) for the validation semantics.
|
|
210
|
+
|
|
191
211
|
## GitHub
|
|
192
212
|
|
|
193
213
|
Point Blume at your repository with `github`. It powers the header [repository link](/docs/content/navigation#repository-link) and the **Edit on GitHub** and **Give feedback** [page actions](/docs/content/navigation#page-actions):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Search
|
|
3
|
-
description: Client-side search out of the box
|
|
3
|
+
description: Client-side search that works out of the box with no API keys, plus optional hosted and semantic backends you can switch to as your docs grow.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Blume ships local search with no hosted infrastructure and no API keys. It runs in the browser, works in both `blume dev` and `blume build`, and indexes only your real content — navigation chrome and excluded pages are skipped. When you outgrow it, you can switch to a hosted or semantic backend without changing how search looks or behaves — only the `search.provider` you configure changes.
|
|
@@ -13,6 +13,33 @@ Open search with <Badge variant="accent">⌘K</Badge> (or `Ctrl K`), or press `/
|
|
|
13
13
|
|
|
14
14
|
Queries match page **titles**, **descriptions**, and **body text**, with title matches ranked highest and descriptions above body.
|
|
15
15
|
|
|
16
|
+
## Popular pages
|
|
17
|
+
|
|
18
|
+
Before a reader types a query, the search dialog shows a **Popular** list. By default it is the first six sidebar pages — which on multi-tab sites often surfaces the wrong section. Pin the links you want instead:
|
|
19
|
+
|
|
20
|
+
```ts blume.config.ts lineNumbers
|
|
21
|
+
search: {
|
|
22
|
+
popular: [
|
|
23
|
+
{ href: "/guides/getting-started", icon: "rocket", label: "Getting started" },
|
|
24
|
+
{ href: "/guides/install", icon: "download", label: "Install" },
|
|
25
|
+
{ href: "/concepts/overview", label: "Overview" },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Each entry takes an `href` (internal route or external URL) and a `label`, plus an optional `icon` — a built-in icon name shown beside the label, defaulting to a file glyph. Omit `popular` or leave it empty to keep the sidebar fallback.
|
|
31
|
+
|
|
32
|
+
Unlike icons elsewhere in Blume, `icon` here must be a built-in name: these rows render in a client island, so an image path or inline SVG isn't supported and falls back to the file glyph.
|
|
33
|
+
|
|
34
|
+
Write `href` as if the site were mounted at the root — a `basePath` is applied for you, the same as `navigation.featured`. External URLs pass through untouched.
|
|
35
|
+
|
|
36
|
+
<Callout type="warning">
|
|
37
|
+
A curated list is a single set of links shared by every language. On a site
|
|
38
|
+
with `i18n` configured, the sidebar fallback follows the reader's locale, but
|
|
39
|
+
`popular` entries point wherever their `href` says — so pin locale-prefixed
|
|
40
|
+
routes only if you want every reader sent to that one language.
|
|
41
|
+
</Callout>
|
|
42
|
+
|
|
16
43
|
## What's indexed
|
|
17
44
|
|
|
18
45
|
For every indexable page, Blume indexes its title, description, and body reduced to plain text — code blocks, images, and markup are stripped, so results stay relevant. The index is built from your source files, so it's identical in dev and production.
|
|
@@ -108,7 +108,7 @@ seo: {
|
|
|
108
108
|
|
|
109
109
|
### Brand the generated card
|
|
110
110
|
|
|
111
|
-
Set a local SVG and
|
|
111
|
+
Set a local SVG and color palette to match the generated card to your brand. The logo can live in `public/` or at the project root. Omit any palette value to keep its default.
|
|
112
112
|
|
|
113
113
|
```ts blume.config.ts lineNumbers
|
|
114
114
|
seo: {
|
|
@@ -144,9 +144,28 @@ seo:
|
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
:::note
|
|
147
|
-
|
|
147
|
+
Every palette color accepts any CSS color — hex, `oklch(…)`, `rgb(…)`, and so on. The accent also accepts a named preset (`blue`, `teal`, …), matching [`theme.accent`](/docs/configuration/theming#accent). A color the renderer can't parse fails the build rather than silently shipping a default-colored card.
|
|
148
148
|
:::
|
|
149
149
|
|
|
150
|
+
Emoji in a page title or site title render as [Twemoji](https://github.com/jdecked/twemoji) glyphs, fetched from a CDN while the card renders — so a build whose titles contain emoji needs network access. Each glyph is fetched once per build, however many pages use it.
|
|
151
|
+
|
|
152
|
+
### Non-Latin titles
|
|
153
|
+
|
|
154
|
+
The card's built-in font covers only Latin glyphs, so a title in another script (Japanese, Chinese, Korean, Arabic, …) renders as tofu — empty boxes. List one or more [Google Fonts](https://fonts.google.com) families in `og.fonts` that cover your script, by name:
|
|
155
|
+
|
|
156
|
+
```ts blume.config.ts lineNumbers
|
|
157
|
+
seo: {
|
|
158
|
+
og: {
|
|
159
|
+
fonts: [
|
|
160
|
+
"Noto Sans JP",
|
|
161
|
+
{ name: "Inter", weight: [400, 700] },
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Each entry is a family name, or an object pinning its `weight` (a number, a list, or a variable range like `"100..900"`) and `style` (`"normal"`, `"italic"`, or both). The families are fetched from Google Fonts at build — so a build that uses them needs network access — and the renderer only pulls the glyph subsets each title actually uses. Fallback is per-glyph, so adding a family only affects glyphs the built-in font can't draw; Latin text renders exactly as before.
|
|
168
|
+
|
|
150
169
|
`seo.image` is frontmatter, so it only covers Markdown and MDX content. To give a custom [`.astro` page](/docs/advanced/custom-pages) its own social image — a marketing home or landing page, and the way to give the home page alone a bespoke share image — pass the `ogImage` prop to `PageLayout`.
|
|
151
170
|
|
|
152
171
|
## RSS feeds
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Theming
|
|
3
|
-
description: Tune the look with config tokens, override any CSS variable in theme.css, or
|
|
3
|
+
description: Tune the look with a handful of config tokens, override any CSS variable in theme.css, or drop down to Tailwind utilities for custom components.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Blume's theme is token-driven and works in light and dark mode out of the box. Reach for as little or as much as you need: a few config tokens for the common cases, a `theme.css` to override any design token, or Tailwind utilities for custom components.
|
|
@@ -69,6 +69,20 @@ Switch between equivalent content in place — language variants, OS-specific co
|
|
|
69
69
|
</Tabs>
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
Add `inline` to render borderless — a tab strip on a full-width rule with the content flowing beneath as prose — instead of the bordered box. Add `param` to sync the active tab to a URL query param instead of the hash, which makes the selection shareable: a link ending in `?install=windows` opens on the Windows tab. Each group syncs to its own `param`, so you can use several independent, deep-linkable groups on one page.
|
|
73
|
+
|
|
74
|
+
<Tabs inline param="install">
|
|
75
|
+
<Tab title="macOS">Use Homebrew to install the toolchain.</Tab>
|
|
76
|
+
<Tab title="Windows">Use winget to install the toolchain.</Tab>
|
|
77
|
+
</Tabs>
|
|
78
|
+
|
|
79
|
+
```astro lineNumbers
|
|
80
|
+
<Tabs inline param="install">
|
|
81
|
+
<Tab title="macOS">Use Homebrew to install the toolchain.</Tab>
|
|
82
|
+
<Tab title="Windows">Use winget to install the toolchain.</Tab>
|
|
83
|
+
</Tabs>
|
|
84
|
+
```
|
|
85
|
+
|
|
72
86
|
## Badge
|
|
73
87
|
|
|
74
88
|
A small inline label for status or metadata — version tags, “new” or “beta” markers, stability levels. The `variant` tunes the color to the meaning.
|
package/docs/content/index.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Pages
|
|
3
|
-
description: How files in your content folder become pages, and how to organize them.
|
|
3
|
+
description: How the files in your content folder become pages, and how to organize and name them so routing and navigation are inferred automatically.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Your docs are just a folder of Markdown and MDX files. Blume turns each file into a page — routing, navigation, and metadata are inferred from the file system, so there's no manifest to keep in sync.
|
package/docs/content/meta.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Folder meta
|
|
3
|
-
description: Configure a sidebar group
|
|
3
|
+
description: Configure a sidebar group with a meta.ts file beside its pages — set the group's title, icon, order, and the order of the pages nested inside.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Every folder in your content tree becomes a sidebar group. Drop a `meta.ts` beside its pages to control how that group looks and how its children are ordered. It's entirely optional: without one, the group's label is the humanized folder name and its pages sort by [index, numeric prefix, then alphabetically](/docs/content/navigation#ordering).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Navigation
|
|
3
|
-
description:
|
|
3
|
+
description: Blume builds the sidebar from your files, then lets you refine it with frontmatter, folder meta, or config — breadcrumbs and outlines follow along.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Blume builds your sidebar from the file system, then lets you refine it as much — or as little — as you want: page by page, folder by folder, or with one explicit config. Breadcrumbs, previous/next links, and the on-page outline all follow from the same model, with nothing to wire up.
|
package/docs/content/sources.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Content sources
|
|
3
|
-
description: Pull docs from local files, a remote
|
|
3
|
+
description: Pull docs from local files, a remote repository, or any custom backend — and mix several sources into one static-first site read at build time.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
By default Blume reads a folder of `.md`/`.mdx` files. **Content sources** let you pull pages from somewhere else — a remote repository, a CMS, or any custom backend — and mix several sources into a single site. Sources are read at build time; Blume stays static-first.
|
package/docs/reference/cli.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: CLI
|
|
3
|
-
description: Every Blume command and flag — init, dev, build, preview, add, sync, and eject.
|
|
3
|
+
description: Every Blume command and flag explained in one place — init, dev, build, preview, add, sync, and eject — along with the options each one accepts.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
```bash
|
|
@@ -21,6 +21,7 @@ blume <command> [options]
|
|
|
21
21
|
| `blume check` | Type-check the site with `astro check`. |
|
|
22
22
|
| `blume doctor` | Diagnose config and content problems. |
|
|
23
23
|
| `blume validate` | Validate links across your content. |
|
|
24
|
+
| `blume audit` | Audit the built site for SEO and health issues. |
|
|
24
25
|
|
|
25
26
|
## Common flags
|
|
26
27
|
|
|
@@ -49,6 +50,14 @@ blume <command> [options]
|
|
|
49
50
|
- `blume validate --external` — also check external links over the network.
|
|
50
51
|
- `blume validate --strict` — exit non-zero on warnings too.
|
|
51
52
|
- `blume validate --json` / `blume doctor --json` — emit diagnostics as JSON on stdout (with `code`, `severity`, `file`, `line`/`column`, and `docsUrl`) for CI and editor integrations.
|
|
53
|
+
- `blume audit --fail-on error|warning|info` — the CI gate; defaults to `error`. `--strict` is an alias for `--fail-on warning`.
|
|
54
|
+
- `blume audit --url <origin>` — also probe a live deployment for status codes, response headers, and redirect chains.
|
|
55
|
+
- `blume audit --external` — probe outbound links over the network.
|
|
56
|
+
- `blume audit --only <check|category>` / `--skip <check|category>` — narrow the report while you work through it (comma-separated).
|
|
57
|
+
- `blume audit --list-checks` — print every check the audit can report.
|
|
58
|
+
- `blume audit --verbose` — list every affected page instead of the first few.
|
|
59
|
+
- `blume audit --json` — emit the report as JSON on stdout.
|
|
60
|
+
- `blume audit --claude` / `--codex` — hand the findings to Claude Code or Codex to fix interactively.
|
|
52
61
|
|
|
53
62
|
## Verifying while the dev server runs
|
|
54
63
|
|
|
@@ -107,3 +116,72 @@ Without a project `tsconfig.json`, only the generated runtime is checked.
|
|
|
107
116
|
- **Anchor links** (`#section`, `/guides/intro#setup`) must match a heading on the target page — misses are warnings.
|
|
108
117
|
- **Asset links** (`/logo.png`) are checked against the `public/` directory.
|
|
109
118
|
- **External links** are only checked with `--external` (off by default since it requires the network); dead links (404/410/unreachable) are errors, while rate-limited or transient responses (403/429/5xx/timeout) are warnings.
|
|
119
|
+
|
|
120
|
+
## Auditing the built site
|
|
121
|
+
|
|
122
|
+
`blume validate` reads your _content_; `blume audit` reads the _built site_. It crawls the HTML in `dist/` after a build and reports SEO and site-health issues — titles, meta descriptions, canonicals, Open Graph and X cards, headings, hreflang, images, the sitemap, `robots.txt`, and structured data.
|
|
123
|
+
|
|
124
|
+
Because Blume built the site, every finding names the source file **and the front matter line** that fixes it, not just the URL a crawler would see:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
⚠ Meta description too long or too short 5 pages
|
|
128
|
+
/docs/configuration/export content/docs/configuration/export.mdx:3
|
|
129
|
+
fix: Rewrite `description` in the frontmatter to fit the length range.
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Run it after a build:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
blume build
|
|
136
|
+
blume audit
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Findings are grouped by check rather than listed per page, so the report reads as a to-do list. Use `--verbose` to expand every affected page, and `--only`/`--skip` to work through one category at a time. `blume audit --list-checks` prints the full catalog.
|
|
140
|
+
|
|
141
|
+
### Failing CI
|
|
142
|
+
|
|
143
|
+
The exit code is the contract. By default `blume audit` fails only on errors — things that are definitely broken, like a link to a page that was never built, a redirect loop, or an invalid sitemap. Advisory findings (a short description, a duplicate title) are warnings and do not fail the build:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
blume audit # fails on errors
|
|
147
|
+
blume audit --fail-on warning # also fails on warnings
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Checking a live deployment
|
|
151
|
+
|
|
152
|
+
Some things only the real server can tell you: whether a page that exists in `dist/` actually 404s behind a bad rewrite, whether responses are compressed, and whether an `X-Robots-Tag` header is quietly deindexing a page whose HTML looks perfectly fine. Point the audit at a deployment to add those checks:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
blume audit --url https://docs.example.com
|
|
156
|
+
blume audit --url https://docs.example.com --external # also probe outbound links
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Outbound links are graded rather than flatly failed: a 404 is a broken link you can fix, while a 403 or 5xx is usually rate limiting or someone else's outage and is reported as a warning.
|
|
160
|
+
|
|
161
|
+
### Fixing the findings with an agent
|
|
162
|
+
|
|
163
|
+
If you use [Claude Code](https://claude.com/claude-code) or [Codex](https://developers.openai.com/codex/cli), the audit can hand its findings straight to it:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
blume audit --claude # or --codex
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
This writes the complete JSON report — every affected page, not the terminal's three-page preview — to a file and opens the agent interactively with a prompt that walks it through the findings: edit the source file each finding names, apply its suggested fix, then run `blume build` and `blume audit` again until the report is clean. The session is interactive by design: you review the edits through the agent's own permission flow, and the agent is told never to fix a finding by deleting content.
|
|
170
|
+
|
|
171
|
+
`--only` and `--skip` narrow the handoff the same way they narrow the report, so you can send one category at a time.
|
|
172
|
+
|
|
173
|
+
### What it does and doesn't check
|
|
174
|
+
|
|
175
|
+
The check set is deliberately narrower than a general-purpose SEO crawler's. Much of what such a crawler reports cannot happen to a Blume site — it never emits `rel=nofollow`, and Vite's content-hashed bundles are never missing or redirecting — and reporting those as permanent zeroes would just teach you to ignore the report.
|
|
176
|
+
|
|
177
|
+
Two limits worth stating plainly:
|
|
178
|
+
|
|
179
|
+
- **Structured data** is validated for well-formedness (valid JSON, a `@context`, a `@type` on every node). Blume does not validate against the full schema.org vocabulary or Google's rich-results rules.
|
|
180
|
+
- **Core Web Vitals** are not checked. They need a real browser, and a flag that quietly measured nothing would be worse than not having one — so `blume audit` reports the layout-shift causes it _can_ see offline (images with no `width`/`height`, oversized assets) and leaves the rest alone for now.
|
|
181
|
+
|
|
182
|
+
Anything the audit did not run is reported as skipped rather than silently passing:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
⊘ network skipped — pass --url <origin> (9 checks)
|
|
186
|
+
⊘ external skipped — pass --external (2 checks)
|
|
187
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Frontmatter
|
|
3
|
-
description: Every frontmatter field a page accepts — title, description, sidebar, SEO, search, and
|
|
3
|
+
description: Every frontmatter field a page accepts, all optional — title, description, sidebar, SEO, search, and the rest, with what each one controls.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Every page accepts the following frontmatter. All fields are optional.
|
|
@@ -81,4 +81,32 @@ changelog:
|
|
|
81
81
|
|
|
82
82
|
`date` may live here or at the top level — both feed the [changelog RSS feed](/docs/content#feeds). See [Changelog](/docs/advanced/changelog) for the generated timeline page and feed.
|
|
83
83
|
|
|
84
|
+
## Custom keys
|
|
85
|
+
|
|
86
|
+
Any key outside this reference fails the build, so typos are caught early. Projects that carry their own metadata can opt extra keys in via [`frontmatter.extend`](/docs/configuration#frontmatter) in `blume.config.ts`, each validated by a schema the project supplies:
|
|
87
|
+
|
|
88
|
+
```ts blume.config.ts lineNumbers
|
|
89
|
+
import { defineConfig } from "blume";
|
|
90
|
+
import { z } from "zod";
|
|
91
|
+
|
|
92
|
+
export default defineConfig({
|
|
93
|
+
frontmatter: {
|
|
94
|
+
extend: {
|
|
95
|
+
owner: z.string(),
|
|
96
|
+
reviewedAt: z.coerce.date().optional(),
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```yaml page.mdx
|
|
103
|
+
---
|
|
104
|
+
title: Install
|
|
105
|
+
owner: "@sam"
|
|
106
|
+
reviewedAt: 2026-06-20
|
|
107
|
+
---
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Schemas are accepted through the [Standard Schema](https://standardschema.dev) interface, so Zod (whichever version your project installs), Valibot, and ArkType all work. Every declared key is validated on every page — absent ones included — so a required schema enforces the key site-wide; mark it `.optional()` to validate only where present. All other keys stay strictly validated, and built-in fields can't be redeclared.
|
|
111
|
+
|
|
84
112
|
Schemas are exported from `blume/schema` for editor and migration tooling.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blume",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Documentation that's fast, AI-ready, and zero-config.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -86,8 +86,6 @@
|
|
|
86
86
|
"@shikijs/twoslash": "^4.2.0",
|
|
87
87
|
"@tailwindcss/typography": "^0.5.20",
|
|
88
88
|
"@tailwindcss/vite": "^4",
|
|
89
|
-
"@takumi-rs/core": "^1.8.7",
|
|
90
|
-
"@takumi-rs/helpers": "^1.8.7",
|
|
91
89
|
"@vercel/analytics": "^2.0.1",
|
|
92
90
|
"ai": "^5.0.0",
|
|
93
91
|
"astro": "^7.0.2",
|
|
@@ -103,6 +101,7 @@
|
|
|
103
101
|
"katex": "^0.17.0",
|
|
104
102
|
"marked": "^18.0.5",
|
|
105
103
|
"mermaid": "^11.15.0",
|
|
104
|
+
"node-html-parser": "^9.0.0",
|
|
106
105
|
"pagefind": "^1.3.0",
|
|
107
106
|
"pathe": "^2.0.0",
|
|
108
107
|
"react": "^19.0.0",
|
|
@@ -111,6 +110,7 @@
|
|
|
111
110
|
"shiki": "^4.2.0",
|
|
112
111
|
"simple-icons": "^13.0.0",
|
|
113
112
|
"tailwindcss": "^4",
|
|
113
|
+
"takumi-js": "^2.2.1",
|
|
114
114
|
"tinyglobby": "^0.2.10",
|
|
115
115
|
"typescript": "^6.0.3",
|
|
116
116
|
"undici": "^8.6.0",
|
|
@@ -66,7 +66,7 @@ The single biggest shift for most sources — especially Mintlify — is that **
|
|
|
66
66
|
- **`content`:** `root` (default `"docs"`, relative to the project dir where `blume` runs), `include`/`exclude` (arrays of globs **relative to `content.root`**; defaults `["**/*.{md,mdx}"]` / `["**/_*", "**/.*"]`), `sources` (staged sources: `filesystem`, `github-releases`, `notion`, `sanity`, `mdx-remote`, `custom` — OpenAPI is **not** one of these; it's the top-level `openapi` field), `pages` (custom `.astro` dir), `defaultType`. When docs sit directly under the project dir (no `docs/` subfolder), set `root` there and **scope `include` to the real content folders** instead of scanning everything — `references/monorepo.md` §1.
|
|
67
67
|
- **`basePath`** (top-level): a site-wide mount point (e.g. `"/docs"`) prepended to **every** route while staying invisible to the sidebar (no wrapper group). This is the right target for a source that served all docs under a prefix (Docusaurus `routeBasePath`, a Fumadocs `baseUrl` of `/docs`) — distinct from a per-source `prefix` (which adds a nav group) and from `deployment.base` (host subdirectory).
|
|
68
68
|
- **`navigation`:** `tabs`, `selectors`, `featured` (links pinned above the sidebar on every route), `sidebar` (`{ display, items }` — `display` is the global render mode above; `items` is an explicit tree), `repo`. **Avoid an explicit `navigation.sidebar` unless you have to** — lean on the filesystem-derived sidebar. It only works when the file tree roughly matches the intended sidebar layout, so reshape folders to match first; reach for `sidebar.items` only for a shape files genuinely can't express (see "Config-declared nesting" above).
|
|
69
|
-
- **`search`** (Orama default, Pagefind opt-in), **`ai`** (llms.txt, Ask AI), **`
|
|
69
|
+
- **`search`** (Orama default, Pagefind opt-in), **`ai`** (llms.txt, Ask AI, the MCP server), **`openapi`**, **`redirects`**, **`seo`**, **`markdown`**, **`analytics`**, **`deployment`**, **`i18n`**, **`toc`**, **`lastModified`**, **`github`**.
|
|
70
70
|
- **Don't set `deployment.site`.** Blume auto-fills it: the dev server's `localhost` URL in dev, and the deployment URL (`VERCEL_PROJECT_PRODUCTION_URL`/`VERCEL_URL`) on Vercel. Hardcoding it in `blume.config.ts` overrides that auto-detection and pins the wrong absolute URL (canonical links, sitemap, OG, llms.txt) everywhere but the one host you typed — so leave it unset even when a source config had a `url`/`site` field. (Sitemap still generates in production because the deploy URL is present there.)
|
|
71
71
|
- **Favicon is a filename convention, not config.** Drop `icon`/`favicon.{svg,png,ico}` (and `apple-icon.png`) in the project root or `public/` — Blume auto-detects it. There is **no** `favicon` config field. A source favicon given as `{ light, dark }` **collapses to one** — pick a single file and report the loss.
|
|
72
72
|
|