blume 2.0.0 → 2.0.1
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/AGENTS.md +1 -1
- package/CHANGELOG.md +28 -0
- package/README.md +2 -2
- package/dist/cli/{chunk-f7t03s3g.js → chunk-27g6wdth.js} +2 -2
- package/dist/cli/{chunk-mnqj32sj.js → chunk-2hn4b8z7.js} +13 -13
- package/dist/cli/chunk-2hn4b8z7.js.map +12 -0
- package/dist/cli/{chunk-by2290sx.js → chunk-5shv93fd.js} +2 -2
- package/dist/cli/{chunk-a9kptbw5.js → chunk-6crbhc3x.js} +3 -3
- package/dist/cli/{chunk-a9kptbw5.js.map → chunk-6crbhc3x.js.map} +1 -1
- package/dist/cli/{chunk-mwt1k8n7.js → chunk-6hsn950k.js} +20 -20
- package/dist/cli/chunk-6hsn950k.js.map +10 -0
- package/dist/cli/{chunk-11j0384y.js → chunk-6vm74dry.js} +13 -13
- package/dist/cli/{chunk-11j0384y.js.map → chunk-6vm74dry.js.map} +3 -3
- package/dist/cli/{chunk-j8mw0za6.js → chunk-79jhk4py.js} +8 -8
- package/dist/cli/{chunk-j8mw0za6.js.map → chunk-79jhk4py.js.map} +2 -2
- package/dist/cli/{chunk-nk3ts2xk.js → chunk-82bbrxdn.js} +2 -2
- package/dist/cli/{chunk-2q1dwty4.js → chunk-ah61y8py.js} +8 -8
- package/dist/cli/{chunk-2q1dwty4.js.map → chunk-ah61y8py.js.map} +4 -4
- package/dist/cli/{chunk-zxccj738.js → chunk-ce574jw2.js} +1 -1
- package/dist/cli/{chunk-y3e45rc8.js → chunk-ch6g3ar0.js} +3 -3
- package/dist/cli/{chunk-beat36xx.js → chunk-dh8cwk36.js} +5 -5
- package/dist/cli/{chunk-beat36xx.js.map → chunk-dh8cwk36.js.map} +2 -2
- package/dist/cli/{chunk-1w8dp3qb.js → chunk-epjnccmv.js} +13 -13
- package/dist/cli/{chunk-ernrthtr.js → chunk-f2z5v128.js} +13 -13
- package/dist/cli/{chunk-zg2gtj10.js → chunk-fs23ddbb.js} +2 -2
- package/dist/cli/{chunk-7ez8ny0t.js → chunk-fxypxtvm.js} +2 -2
- package/dist/cli/{chunk-tzne8qfq.js → chunk-fz5wtpmh.js} +13 -13
- package/dist/cli/{chunk-b5aj94ah.js → chunk-hdpx1tax.js} +4 -4
- package/dist/cli/{chunk-d80hr03s.js → chunk-jwyddg7y.js} +9 -9
- package/dist/cli/{chunk-d80hr03s.js.map → chunk-jwyddg7y.js.map} +2 -2
- package/dist/cli/{chunk-fh5hj5jt.js → chunk-kdp5q7ke.js} +15 -15
- package/dist/cli/{chunk-6k8vp3ta.js → chunk-kpf8rrjc.js} +9 -9
- package/dist/cli/{chunk-6k8vp3ta.js.map → chunk-kpf8rrjc.js.map} +3 -3
- package/dist/cli/{chunk-5a2z0198.js → chunk-m3vmjgmq.js} +9 -9
- package/dist/cli/{chunk-5a2z0198.js.map → chunk-m3vmjgmq.js.map} +2 -2
- package/dist/cli/{chunk-bctazmbk.js → chunk-mb2919y2.js} +4 -4
- package/dist/cli/{chunk-79njf86q.js → chunk-q5163e60.js} +13 -13
- package/dist/cli/{chunk-xaz13gwg.js → chunk-qkqwkpte.js} +196 -208
- package/dist/cli/{chunk-xaz13gwg.js.map → chunk-qkqwkpte.js.map} +48 -48
- package/dist/cli/{chunk-sqn5t4q0.js → chunk-qs4q5p4e.js} +3 -3
- package/dist/cli/{chunk-bw22s759.js → chunk-qwsrynx5.js} +1 -1
- package/dist/cli/{chunk-z01ze5c1.js → chunk-s1p84fyh.js} +15 -15
- package/dist/cli/{chunk-pnnvybbk.js → chunk-s6jhgk0q.js} +5 -5
- package/dist/cli/{chunk-pnnvybbk.js.map → chunk-s6jhgk0q.js.map} +2 -2
- package/dist/cli/{chunk-f2972sbt.js → chunk-vtk4a6dg.js} +1 -1
- package/dist/cli/{chunk-z1f5arsg.js → chunk-wgm7m9qk.js} +21 -21
- package/dist/cli/{chunk-z1f5arsg.js.map → chunk-wgm7m9qk.js.map} +4 -4
- package/dist/cli/{chunk-bnbmcwfb.js → chunk-wm7js3j9.js} +5 -5
- package/dist/cli/{chunk-bnbmcwfb.js.map → chunk-wm7js3j9.js.map} +3 -3
- package/dist/cli/{chunk-d1tadaw7.js → chunk-yt5n7ppj.js} +3 -3
- package/dist/cli/{chunk-pat2zzwc.js → chunk-yw7dm696.js} +1 -1
- package/dist/cli/{chunk-pat2zzwc.js.map → chunk-yw7dm696.js.map} +1 -1
- package/dist/cli/{chunk-88cpgt6h.js → chunk-zxcczpyx.js} +1 -1
- package/dist/cli/{chunk-41za066z.js → chunk-zxh4d9vy.js} +4 -4
- package/dist/cli/index.js +17 -17
- package/dist/types/ai/agent-readability.d.ts +1 -1
- package/dist/types/ai/api/paths.d.ts +1 -1
- package/dist/types/ai/ask-context.d.ts +7 -7
- package/dist/types/ai/ask.d.ts +43 -43
- package/dist/types/ai/index.d.ts +3 -3
- package/dist/types/ai/openapi-components.d.ts +1 -1
- package/dist/types/ai/serializers.d.ts +1 -1
- package/dist/types/ai/visibility.d.ts +1 -1
- package/dist/types/core/config-input.d.ts +17 -17
- package/dist/types/core/config.d.ts +3 -3
- package/dist/types/core/data.d.ts +3 -3
- package/dist/types/core/i18n-ui.d.ts +6 -8
- package/dist/types/core/schema.d.ts +5 -5
- package/dist/types/core/unrecognized-keys.d.ts +1 -1
- package/dist/types/search/documents.d.ts +1 -1
- package/dist/types/search/orama-index.d.ts +1 -1
- package/docs/02-deployment.mdx +4 -4
- package/docs/03-upgrading.mdx +22 -9
- package/docs/04-migrating.mdx +4 -4
- package/docs/08-faq.mdx +3 -3
- package/docs/advanced/custom-pages.mdx +2 -2
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +3 -3
- package/docs/cli/doctor.mdx +3 -3
- package/docs/cli/evals.mdx +7 -7
- package/docs/cli/index.mdx +2 -2
- package/docs/cli/translate.mdx +8 -8
- package/docs/configuration/{ask-ai.mdx → assistant.mdx} +19 -19
- package/docs/configuration/customization.mdx +2 -2
- package/docs/configuration/index.mdx +2 -2
- package/docs/configuration/meta.ts +1 -1
- package/docs/configuration/search.mdx +1 -1
- package/docs/content/i18n.mdx +2 -2
- package/docs/content/islands.mdx +1 -1
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/index.mdx +1 -1
- package/docs/index.mdx +2 -2
- package/package.json +1 -1
- package/skills/blume/SKILL.md +5 -5
- package/skills/blume-migrate/SKILL.md +2 -2
- package/src/ai/agent-readability.ts +4 -4
- package/src/ai/api/paths.ts +1 -1
- package/src/ai/ask-context.ts +7 -7
- package/src/ai/ask-data.ts +2 -2
- package/src/ai/ask.ts +84 -71
- package/src/ai/cors.ts +3 -3
- package/src/ai/index.ts +16 -16
- package/src/ai/openapi-components.ts +1 -1
- package/src/ai/serializers.ts +1 -1
- package/src/ai/visibility.ts +1 -1
- package/src/astro/generate.ts +19 -18
- package/src/astro/module-types.ts +1 -1
- package/src/astro/runtime-deps.ts +6 -6
- package/src/astro/templates.ts +26 -26
- package/src/blume-modules.d.ts +2 -2
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/doctor.ts +7 -5
- package/src/cli/commands/eval.ts +3 -3
- package/src/cli/commands/migrate.ts +2 -2
- package/src/cli/commands/translate.ts +3 -3
- package/src/cli/commands/upgrade.ts +2 -2
- package/src/cli/required-secrets.ts +3 -3
- package/src/components/copy-feedback.ts +1 -1
- package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
- package/src/components/islands/{ask-ai.tsx → assistant.tsx} +23 -23
- package/src/components/islands/hooks.ts +14 -12
- package/src/components/layout/Header.astro +10 -10
- package/src/components/layout/PageLayout.astro +6 -6
- package/src/components/layout/Pagination.astro +7 -7
- package/src/components/layout/ReferenceLayout.astro +1 -1
- package/src/components/layout/RootLayout.astro +6 -6
- package/src/components/layout/Search.astro +13 -13
- package/src/components/layout/analytics-client.ts +1 -1
- package/src/components/layout/drawer-inert.ts +1 -1
- package/src/components/openapi/description.ts +2 -2
- package/src/core/code-fences.ts +1 -1
- package/src/core/config-input.ts +19 -19
- package/src/core/config.ts +3 -3
- package/src/core/data.ts +3 -3
- package/src/core/i18n-ui.ts +35 -9
- package/src/core/request-body.ts +1 -1
- package/src/core/schema.ts +25 -20
- package/src/core/server-features.ts +2 -2
- package/src/core/ui-packs/ar.ts +4 -5
- package/src/core/ui-packs/bg.ts +4 -5
- package/src/core/ui-packs/bn.ts +4 -5
- package/src/core/ui-packs/ca.ts +4 -5
- package/src/core/ui-packs/cs.ts +4 -5
- package/src/core/ui-packs/da.ts +4 -5
- package/src/core/ui-packs/de.ts +4 -5
- package/src/core/ui-packs/el.ts +4 -5
- package/src/core/ui-packs/es.ts +4 -5
- package/src/core/ui-packs/fa.ts +4 -5
- package/src/core/ui-packs/fi.ts +4 -5
- package/src/core/ui-packs/fr.ts +4 -5
- package/src/core/ui-packs/he.ts +4 -5
- package/src/core/ui-packs/hi.ts +4 -5
- package/src/core/ui-packs/hr.ts +4 -5
- package/src/core/ui-packs/hu.ts +4 -5
- package/src/core/ui-packs/id.ts +4 -5
- package/src/core/ui-packs/it.ts +4 -5
- package/src/core/ui-packs/ja.ts +4 -5
- package/src/core/ui-packs/ko.ts +4 -5
- package/src/core/ui-packs/nl.ts +4 -5
- package/src/core/ui-packs/no.ts +4 -5
- package/src/core/ui-packs/pl.ts +4 -5
- package/src/core/ui-packs/pt-br.ts +4 -5
- package/src/core/ui-packs/pt.ts +4 -5
- package/src/core/ui-packs/ro.ts +4 -5
- package/src/core/ui-packs/ru.ts +4 -5
- package/src/core/ui-packs/sk.ts +4 -5
- package/src/core/ui-packs/sr.ts +4 -5
- package/src/core/ui-packs/sv.ts +4 -5
- package/src/core/ui-packs/th.ts +4 -5
- package/src/core/ui-packs/tr.ts +4 -5
- package/src/core/ui-packs/uk.ts +4 -5
- package/src/core/ui-packs/vi.ts +4 -5
- package/src/core/ui-packs/zh-tw.ts +4 -5
- package/src/core/ui-packs/zh.ts +4 -5
- package/src/core/unrecognized-keys.ts +1 -1
- package/src/registry/eject.ts +19 -18
- package/src/search/documents.ts +2 -2
- package/src/search/orama-index.ts +1 -1
- package/src/translate/report.ts +1 -1
- package/src/upgrade/upgrade.ts +1 -1
- package/dist/cli/chunk-mnqj32sj.js.map +0 -12
- package/dist/cli/chunk-mwt1k8n7.js.map +0 -10
- /package/dist/cli/{chunk-f7t03s3g.js.map → chunk-27g6wdth.js.map} +0 -0
- /package/dist/cli/{chunk-by2290sx.js.map → chunk-5shv93fd.js.map} +0 -0
- /package/dist/cli/{chunk-nk3ts2xk.js.map → chunk-82bbrxdn.js.map} +0 -0
- /package/dist/cli/{chunk-zxccj738.js.map → chunk-ce574jw2.js.map} +0 -0
- /package/dist/cli/{chunk-y3e45rc8.js.map → chunk-ch6g3ar0.js.map} +0 -0
- /package/dist/cli/{chunk-1w8dp3qb.js.map → chunk-epjnccmv.js.map} +0 -0
- /package/dist/cli/{chunk-ernrthtr.js.map → chunk-f2z5v128.js.map} +0 -0
- /package/dist/cli/{chunk-zg2gtj10.js.map → chunk-fs23ddbb.js.map} +0 -0
- /package/dist/cli/{chunk-7ez8ny0t.js.map → chunk-fxypxtvm.js.map} +0 -0
- /package/dist/cli/{chunk-tzne8qfq.js.map → chunk-fz5wtpmh.js.map} +0 -0
- /package/dist/cli/{chunk-b5aj94ah.js.map → chunk-hdpx1tax.js.map} +0 -0
- /package/dist/cli/{chunk-fh5hj5jt.js.map → chunk-kdp5q7ke.js.map} +0 -0
- /package/dist/cli/{chunk-bctazmbk.js.map → chunk-mb2919y2.js.map} +0 -0
- /package/dist/cli/{chunk-79njf86q.js.map → chunk-q5163e60.js.map} +0 -0
- /package/dist/cli/{chunk-sqn5t4q0.js.map → chunk-qs4q5p4e.js.map} +0 -0
- /package/dist/cli/{chunk-bw22s759.js.map → chunk-qwsrynx5.js.map} +0 -0
- /package/dist/cli/{chunk-z01ze5c1.js.map → chunk-s1p84fyh.js.map} +0 -0
- /package/dist/cli/{chunk-f2972sbt.js.map → chunk-vtk4a6dg.js.map} +0 -0
- /package/dist/cli/{chunk-d1tadaw7.js.map → chunk-yt5n7ppj.js.map} +0 -0
- /package/dist/cli/{chunk-88cpgt6h.js.map → chunk-zxcczpyx.js.map} +0 -0
- /package/dist/cli/{chunk-41za066z.js.map → chunk-zxh4d9vy.js.map} +0 -0
package/docs/03-upgrading.mdx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Upgrade to Blume 2
|
|
3
|
-
description: Move a Blume 1 site to Blume 2 with one command, then use this guide for each config change — or hand the whole upgrade to Claude Code
|
|
3
|
+
description: Move a Blume 1 site to Blume 2 with one command, then use this guide for each config change — or hand the whole upgrade to Codex or Claude Code.
|
|
4
4
|
sidebar:
|
|
5
5
|
label: Upgrade to Blume 2
|
|
6
6
|
order: 2.5
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
Blume 2 changes configuration, not content: your Markdown and MDX pages need no edits, unless one sets the removed `search.boost` frontmatter field (see [Frontmatter](#frontmatter)). Settings that used to be a named string or a keyed block — the search provider, the deployment target, content sources, API references, analytics, and the
|
|
9
|
+
Blume 2 changes configuration, not content: your Markdown and MDX pages need no edits, unless one sets the removed `search.boost` frontmatter field (see [Frontmatter](#frontmatter)). Settings that used to be a named string or a keyed block — the search provider, the deployment target, content sources, API references, analytics, and the assistant's model backend — are now **adapters** you import from a `blume/*` subpath and call. Ask AI is renamed the assistant, so `ai.ask` becomes `ai.assistant`. The machine-readable settings move from `ai` to a new `agents` key, and `components.ts` overrides are checked before the build. A zero-config site, or one that sets none of these, only needs the version bump.
|
|
10
10
|
|
|
11
11
|
## Upgrade with one command
|
|
12
12
|
|
|
@@ -18,10 +18,10 @@ npx blume@latest upgrade
|
|
|
18
18
|
|
|
19
19
|
It bumps `blume` in your `package.json` to 2, installs it with the package manager your project uses, then checks your config and `components.ts` against Blume 2. Every change that's still needed is listed with its file, line, and replacement — including `package.json` scripts that still pass the removed `blume build` flags — and the command exits non-zero until none are left. Run from a folder with neither a config nor a `blume` dependency, it stops with an error instead. Run it through `npx blume@latest` rather than `blume`: the command ships in Blume 2, so a project still on 1 doesn't have it yet. On pnpm 12, add `--allow-build=esbuild` after `pnpm dlx`, since pnpm 12 won't run esbuild's install script unapproved.
|
|
20
20
|
|
|
21
|
-
To hand the changes to a coding agent instead, add `--
|
|
21
|
+
To hand the changes to a coding agent instead, add `--codex` or `--claude`:
|
|
22
22
|
|
|
23
23
|
```package-install
|
|
24
|
-
npx blume@latest upgrade --
|
|
24
|
+
npx blume@latest upgrade --codex
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
The agent opens interactively with the findings and this guide, applies each change, and runs `blume doctor` and `blume build` until both pass, so you review every edit through its own permission flow. Pass `--no-install` to bump `package.json` without installing.
|
|
@@ -201,9 +201,9 @@ export default defineConfig({
|
|
|
201
201
|
|
|
202
202
|
`cloudflare: { token }` becomes `cloudflare({ token })`, and each `scripts[]` entry becomes `script({ … })`.
|
|
203
203
|
|
|
204
|
-
##
|
|
204
|
+
## Assistant
|
|
205
205
|
|
|
206
|
-
`ai.ask.provider` takes an adapter from `blume/ai`, which owns the model and the fields that went with it.
|
|
206
|
+
Ask AI is now called the assistant, and its config moves with the name: `ai.ask` becomes `ai.assistant`. Its `provider` takes an adapter from `blume/ai`, which owns the model and the fields that went with it.
|
|
207
207
|
|
|
208
208
|
<CodeGroup>
|
|
209
209
|
|
|
@@ -226,7 +226,7 @@ import { openrouter } from "blume/ai";
|
|
|
226
226
|
|
|
227
227
|
export default defineConfig({
|
|
228
228
|
ai: {
|
|
229
|
-
|
|
229
|
+
assistant: {
|
|
230
230
|
enabled: true,
|
|
231
231
|
provider: openrouter({
|
|
232
232
|
model: "anthropic/claude-sonnet-4-5",
|
|
@@ -239,7 +239,20 @@ export default defineConfig({
|
|
|
239
239
|
|
|
240
240
|
</CodeGroup>
|
|
241
241
|
|
|
242
|
-
The adapters are `gateway()`, `openrouter()`, `llmgateway()`, `inkeep()`, and `openaiCompatible({ baseUrl, name, model, apiKeyEnv })`. `model`, `apiKeyEnv`, `baseUrl`, `headers`, and `reasoning` move into the adapter; `enabled`, `instructions`, `retrieval`, `suggestions`, `cors`, and `endpoint`
|
|
242
|
+
The adapters are `gateway()`, `openrouter()`, `llmgateway()`, `inkeep()`, and `openaiCompatible({ baseUrl, name, model, apiKeyEnv })`. `model`, `apiKeyEnv`, `baseUrl`, `headers`, and `reasoning` move into the adapter; `enabled`, `instructions`, `retrieval`, `suggestions`, `cors`, and `endpoint` move to `ai.assistant` unchanged. Leaving `provider` unset still uses the AI Gateway.
|
|
243
|
+
|
|
244
|
+
The rename reaches every name that said Ask AI:
|
|
245
|
+
|
|
246
|
+
- `i18n.ui` overrides: the `ask` group becomes `assistant`, and `search.askAi` and `search.askAiHint` become `search.assistant` and `search.assistantHint`.
|
|
247
|
+
- `useAskAI` from `blume/hooks` becomes `useAssistant`, with its `UseAssistant` and `UseAssistantOptions` types.
|
|
248
|
+
- The `askEnabled` prop on `PageLayout`, `RootLayout`, `Header`, and a `Search` override becomes `assistantEnabled`.
|
|
249
|
+
- In the [`blume:data`](/docs/advanced/custom-pages) module, `config.ask` becomes `config.assistant` and `ui.ask` becomes `ui.assistant`, and the `UIStrings` type from `blume` follows.
|
|
250
|
+
- The adapter types from `blume/ai` swap their `Ask` prefix for `Assistant` (`AskAdapter` becomes `AssistantAdapter`, `AskGatewayOptions` becomes `AssistantGatewayOptions`), and `askReasoningLevels` and `AskReasoning` from `blume/schema` become `assistantReasoningLevels` and `AssistantReasoning`.
|
|
251
|
+
- The `blume:open-ask-ai` window event becomes `blume:open-assistant`, and the `data-blume-ask` attribute on `<body>` becomes `data-blume-assistant`.
|
|
252
|
+
|
|
253
|
+
The generated `/api/ask` route and the `ask`, `ask_answer`, and `ask_error` [analytics events](/docs/configuration/assistant#analytics) keep their names, so callers and dashboards need no change. `blume upgrade` and `blume doctor` name each old config key they find, `ai.ask` and the `i18n.ui` keys alike, with its replacement.
|
|
254
|
+
|
|
255
|
+
Upgraded to Blume 2.0.0 already? It still read `ai.ask`, so update `blume` as usual and make the same rename.
|
|
243
256
|
|
|
244
257
|
## Agents and other config moves
|
|
245
258
|
|
|
@@ -270,7 +283,7 @@ export default defineConfig({
|
|
|
270
283
|
|
|
271
284
|
</CodeGroup>
|
|
272
285
|
|
|
273
|
-
- `ai.api`, `ai.catalog`, `ai.llmsTxt`, `ai.markdownComponents`, `ai.mcp`, `ai.skills`, `ai.webBotAuth`, and `ai.webmcp` become `agents.*`, and so do `seo.agentReadability` and `seo.contentSignals`. `ai` keeps only `ask` and `openInChat`.
|
|
286
|
+
- `ai.api`, `ai.catalog`, `ai.llmsTxt`, `ai.markdownComponents`, `ai.mcp`, `ai.skills`, `ai.webBotAuth`, and `ai.webmcp` become `agents.*`, and so do `seo.agentReadability` and `seo.contentSignals`. `ai` keeps only `assistant` (formerly `ask`) and `openInChat`.
|
|
274
287
|
- `lastModified` is a flat value: `true` becomes `"git"`, and `{ type: "git" }` or `{ type: "frontmatter" }` becomes the bare string.
|
|
275
288
|
- `markdown.codeBlocks` merges into `markdown.code`.
|
|
276
289
|
- `theme.layout` is gone. Nothing read it, so delete it.
|
package/docs/04-migrating.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Migrate to Blume
|
|
3
|
-
description: Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with one command that hands the migration to Claude Code
|
|
3
|
+
description: Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with one command that hands the migration to Codex or Claude Code.
|
|
4
4
|
sidebar:
|
|
5
5
|
label: Migrate to Blume
|
|
6
6
|
order: 2.4
|
|
@@ -13,10 +13,10 @@ Moving a docs site to idiomatic Blume takes judgment a codemod can't make: which
|
|
|
13
13
|
Run it from the root of the docs project you're migrating:
|
|
14
14
|
|
|
15
15
|
```package-install
|
|
16
|
-
npx blume migrate fumadocs --
|
|
16
|
+
npx blume migrate fumadocs --codex
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
Swap `fumadocs` for your framework, and `--
|
|
19
|
+
Swap `fumadocs` for your framework, and `--codex` for `--claude` to use Claude Code. With pnpm 12, add `--allow-build=esbuild` after `pnpm dlx`, since pnpm 12 won't run esbuild's install script unapproved. The agent opens interactively in your terminal, so every edit goes through its own permission flow. It works in place, so start from a clean working tree and review the whole migration as one diff.
|
|
20
20
|
|
|
21
21
|
## Sources
|
|
22
22
|
|
|
@@ -47,7 +47,7 @@ It finishes with a summary of what it migrated, dropped, or approximated, such a
|
|
|
47
47
|
|
|
48
48
|
## Other agents
|
|
49
49
|
|
|
50
|
-
Without `--
|
|
50
|
+
Without `--codex` or `--claude`, the command reports the source it detected, prints the path to the playbook — the `blume-migrate` [skill](/docs/advanced/skills) bundled in the package — and exits without changing anything. Point any other agent at that `SKILL.md`, or install the skill where your agent looks for skills, with the command it prints:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
53
|
npx skills add haydenbleasel/blume --skill blume-migrate
|
package/docs/08-faq.mdx
CHANGED
|
@@ -20,13 +20,13 @@ Blume takes a third path: **the framework is the template.** You point it at a f
|
|
|
20
20
|
| **Hosting** | Anywhere — static or a server function | Their managed infrastructure | Anywhere; you build and deploy |
|
|
21
21
|
| **You maintain** | Your Markdown | Your Markdown + platform config | Your Markdown + the app around it |
|
|
22
22
|
| **Rendering** | Astro; core theme ships zero client JS | Their runtime | React/Next.js runtime |
|
|
23
|
-
| **AI features** | `llms.txt`, raw Markdown,
|
|
23
|
+
| **AI features** | `llms.txt`, raw Markdown, an in-page assistant, MCP — built in, no hosted service | Built in (hosted) | Bring your own |
|
|
24
24
|
|
|
25
25
|
A few consequences worth calling out:
|
|
26
26
|
|
|
27
27
|
- **You own the output.** `blume build` produces a plain site you host on Vercel, Netlify, Cloudflare, S3, or your own box. Nothing phones home.
|
|
28
28
|
- **No lock-in, two ways out.** Your content is portable Markdown, and `blume eject` turns the project into a standalone Astro app that still uses the `blume` package when you want full control.
|
|
29
|
-
- **Fast by default.** The core theme is React-free and renders static HTML, so pages score well on Core Web Vitals without tuning. You opt into server features (
|
|
29
|
+
- **Fast by default.** The core theme is React-free and renders static HTML, so pages score well on Core Web Vitals without tuning. You opt into server features (the assistant, MCP) only when you need them.
|
|
30
30
|
- **Type-safe configuration.** `blume.config.ts` and every `meta.ts` are real TypeScript validated by a schema — not loosely-typed YAML.
|
|
31
31
|
|
|
32
32
|
:::note
|
|
@@ -49,7 +49,7 @@ Yes. Any page can be `.md` or `.mdx`, and MDX lets you drop in the [built-in com
|
|
|
49
49
|
|
|
50
50
|
## Where can I deploy it?
|
|
51
51
|
|
|
52
|
-
Anywhere. `blume build` outputs static HTML by default, which you can serve from any static host or CDN — Vercel, Netlify, Cloudflare Pages, GitHub Pages, S3, or your own server. Server-only features (
|
|
52
|
+
Anywhere. `blume build` outputs static HTML by default, which you can serve from any static host or CDN — Vercel, Netlify, Cloudflare Pages, GitHub Pages, S3, or your own server. Server-only features (the assistant, the MCP server, on-demand rendering) need server output: name a host adapter from `blume/deploy` — `vercel()`, `netlify()`, `cloudflare()`, or `node()` — as `deployment`. See [Deployment](/docs/deployment).
|
|
53
53
|
|
|
54
54
|
## Does search need a hosted service?
|
|
55
55
|
|
|
@@ -76,7 +76,7 @@ The module exposes:
|
|
|
76
76
|
type: "BlumeDataConfig",
|
|
77
77
|
required: true,
|
|
78
78
|
description:
|
|
79
|
-
"Resolved site settings: title, description, logo, favicon, appleIcon, banner, theme, site, repoUrl, github (owner, repo, host, and the REST api base — null when unset), search, i18n, mcp,
|
|
79
|
+
"Resolved site settings: title, description, logo, favicon, appleIcon, banner, theme, site, repoUrl, github (owner, repo, host, and the REST api base — null when unset), search, i18n, mcp, assistant, og, analytics, feedback, structuredData, toc, codeThemes, codeWrap, and imageZoom.",
|
|
80
80
|
},
|
|
81
81
|
navigation: {
|
|
82
82
|
type: "Navigation",
|
|
@@ -230,7 +230,7 @@ const { config } = data;
|
|
|
230
230
|
</PageLayout>
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
-
The header a custom page gets is the same one the docs pages get, so the chrome that lives in it comes along: search, the theme toggle, the language switcher, and — when [
|
|
233
|
+
The header a custom page gets is the same one the docs pages get, so the chrome that lives in it comes along: search, the theme toggle, the language switcher, and — when the [assistant](/docs/configuration/assistant) is configured — its trigger. None of it needs wiring up per page. Pass `assistantEnabled={false}` to leave the assistant trigger off one page while keeping it everywhere else.
|
|
234
234
|
|
|
235
235
|
The [agent-discovery head links](/docs/discoverability/agent-discovery#discovery-link-header) come along too: the layout reads the resolved config, so a custom page carries the same `describedby`, `ai-catalog`, and `ard` links the docs pages do without passing a prop. The homepage also advertises its `/index.md` Markdown mirror as a `text/markdown` alternate, since that mirror always exists; other custom pages have none, so none is advertised. Pass `discovery={null}` to drop the links from one page.
|
|
236
236
|
|
package/docs/advanced/skills.mdx
CHANGED
|
@@ -15,7 +15,7 @@ npx skills add haydenbleasel/blume
|
|
|
15
15
|
|
|
16
16
|
## Migration
|
|
17
17
|
|
|
18
|
-
`blume-migrate` moves an existing docs site to Blume: Mintlify, Fumadocs, Docusaurus, Starlight, Nextra, or any other framework. It targets idiomatic Blume rather than a line-by-line port, with a mapping reference for each named framework, a redirect for every URL that moves, and a report of anything it drops. The quickest way to run it is [`blume migrate`](/docs/migrating), which detects your framework and opens Claude Code
|
|
18
|
+
`blume-migrate` moves an existing docs site to Blume: Mintlify, Fumadocs, Docusaurus, Starlight, Nextra, or any other framework. It targets idiomatic Blume rather than a line-by-line port, with a mapping reference for each named framework, a redirect for every URL that moves, and a report of anything it drops. The quickest way to run it is [`blume migrate`](/docs/migrating), which detects your framework and opens Codex or Claude Code on the copy bundled in the package. To use it from another agent, install it:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
npx skills add haydenbleasel/blume --skill blume-migrate
|
package/docs/cli/audit.mdx
CHANGED
|
@@ -31,7 +31,7 @@ Findings are grouped by check rather than listed per page, so the report reads a
|
|
|
31
31
|
- `--list-checks` — print every check the audit can report, then exit.
|
|
32
32
|
- `--verbose` — list every affected page with each finding's full detail, instead of the first few.
|
|
33
33
|
- `--json` — emit the report as JSON on stdout.
|
|
34
|
-
- `--
|
|
34
|
+
- `--codex` / `--claude` — hand the findings to Codex or Claude Code to fix interactively.
|
|
35
35
|
|
|
36
36
|
## Failing CI
|
|
37
37
|
|
|
@@ -55,10 +55,10 @@ Outbound links are graded rather than flatly failed: a 404 is a broken link you
|
|
|
55
55
|
|
|
56
56
|
## Fixing the findings with an agent
|
|
57
57
|
|
|
58
|
-
If you use [
|
|
58
|
+
If you use [Codex](https://developers.openai.com/codex/cli) or [Claude Code](https://claude.com/claude-code), the audit can hand its findings straight to it:
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
|
-
blume audit --
|
|
61
|
+
blume audit --codex # or --claude
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
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.
|
package/docs/cli/doctor.mdx
CHANGED
|
@@ -14,15 +14,15 @@ blume doctor
|
|
|
14
14
|
- **The Node version** against the range the installed `blume` package supports, read from its own `engines` field. A version outside it is a warning: things may work, but it isn't a combination Blume tests.
|
|
15
15
|
- **`blume.config.ts`**, with the same validation a build runs. A removed or renamed key fails with a hint naming its replacement rather than a bare "unrecognized key".
|
|
16
16
|
- **Every content page and folder meta**: the diagnostics `blume dev` and `blume build` print as they load the project — invalid frontmatter, navigation problems, missing include targets, and the rest — collected in one report.
|
|
17
|
-
- **Features that need a server** on a site configured for static output —
|
|
18
|
-
- **Packages your config needs** that aren't installed — the SDK a search, content source, or
|
|
17
|
+
- **Features that need a server** on a site configured for static output — the assistant, the MCP server, or the Try it playground's built-in proxy: an error naming the feature, with the deployment adapter to switch to (or, when a host adapter is set to `output: "static"`, telling you to drop that option).
|
|
18
|
+
- **Packages your config needs** that aren't installed — the SDK a search, content source, or assistant adapter imports, a deployment adapter's `@astrojs/*` package, or the renderer for Vue or Svelte islands: an error naming each package, with the install command for your package manager. `blume build` stops on the same check.
|
|
19
19
|
- **`components.ts` overrides** Blume can't plan — an inline or computed entry, or an import whose file doesn't exist: an error for each, at its line.
|
|
20
20
|
- **A version-shaped folder** (`v1.0/`) on a site with no `versions` configured, which would otherwise build as ordinary content: a warning pointing at [`blume version`](/docs/cli/version).
|
|
21
21
|
- **Secrets an enabled feature reads** that aren't set, such as `ALGOLIA_ADMIN_API_KEY` or `OPENROUTER_API_KEY`: a warning naming the variable. Doctor loads `.env` and `.env.local` first, like `blume dev` and `blume build`.
|
|
22
22
|
|
|
23
23
|
## The summary
|
|
24
24
|
|
|
25
|
-
After the diagnostics, doctor prints what the project resolved to, so a mismatch between what you think is configured and what Blume sees is visible at a glance: the page count, the output mode and deployment adapter, the search provider, the configured reference, analytics, and content source adapters, and whether
|
|
25
|
+
After the diagnostics, doctor prints what the project resolved to, so a mismatch between what you think is configured and what Blume sees is visible at a glance: the page count, the output mode and deployment adapter, the search provider, the configured reference, analytics, and content source adapters, and whether the assistant is on and which backend it uses.
|
|
26
26
|
|
|
27
27
|
## Exit code and JSON
|
|
28
28
|
|
package/docs/cli/evals.mdx
CHANGED
|
@@ -10,22 +10,22 @@ blume eval
|
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
```
|
|
13
|
-
blume eval 4 question(s) ·
|
|
13
|
+
blume eval 4 question(s) · Codex
|
|
14
14
|
|
|
15
|
-
✔ install-node-version pass 1.00 14.2s
|
|
16
|
-
✔ custom-domain pass 0.92 21.3s
|
|
17
|
-
✖ deploy-vercel fail 0.40 38.9s
|
|
15
|
+
✔ install-node-version pass 1.00 14.2s
|
|
16
|
+
✔ custom-domain pass 0.92 21.3s
|
|
17
|
+
✖ deploy-vercel fail 0.40 38.9s
|
|
18
18
|
missing: deployment: vercel() from blume/deploy
|
|
19
19
|
⊘ search-providers skipped
|
|
20
20
|
|
|
21
21
|
fix: content/docs/deployment.mdx Docs could not answer: "How do I deploy to Vercel?" — missing: deployment: vercel() from blume/deploy
|
|
22
22
|
|
|
23
|
-
2 passed · 1 failed · 1 skipped · 1m 42s
|
|
23
|
+
2 passed · 1 failed · 1 skipped · 1m 42s
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## How it works
|
|
27
27
|
|
|
28
|
-
Each question runs through two agent sessions, using an agent CLI you already have installed — [
|
|
28
|
+
Each question runs through two agent sessions, using an agent CLI you already have installed — [Codex](https://developers.openai.com/codex/cli) by default, or [Claude Code](https://claude.com/claude-code) with `--agent claude`. Blume holds no API keys and calls no model itself. With Codex, both sessions also run without Codex's shell, command, and image tools, and inherit none of your environment variables.
|
|
29
29
|
|
|
30
30
|
1. **The reader** answers the question using _only_ your documentation. It runs in an empty directory with its file, shell, and web tools disabled, connected to a private [MCP server](/docs/discoverability/mcp) that serves your docs — the same `search_docs`/`get_page` tools a real agent uses against your deployed site. It cannot read your repo, so it experiences the docs exactly like a fresh user: what isn't written doesn't exist.
|
|
31
31
|
2. **The judge** grades the answer against the facts you listed, with no tools at all. Paraphrase passes; a missing or contradicted fact fails — and so does "the documentation doesn't say."
|
|
@@ -98,7 +98,7 @@ This writes the full JSON report to a file and opens the agent interactively wit
|
|
|
98
98
|
|
|
99
99
|
## Flags
|
|
100
100
|
|
|
101
|
-
- `--agent claude
|
|
101
|
+
- `--agent codex|claude` — which agent CLI runs the reader and judge. Defaults to `codex`.
|
|
102
102
|
- `--file <path>` — the evals file. Defaults to `evals.yaml`.
|
|
103
103
|
- `--threshold <0..1>` — minimum passing fraction before the run exits non-zero. Defaults to `1`.
|
|
104
104
|
- `--timeout <seconds>` — reader time limit per question. Defaults to `180`.
|
package/docs/cli/index.mdx
CHANGED
|
@@ -25,8 +25,8 @@ blume <command> [options]
|
|
|
25
25
|
| [`blume eval`](/docs/cli/evals) | Test the docs: an agent answers your questions using only the documentation. |
|
|
26
26
|
| [`blume translate`](/docs/cli/translate) | Translate docs into the configured locales with a local agent CLI. |
|
|
27
27
|
| [`blume version [id]`](/docs/cli/version) | Freeze the current docs as an archived version (no id lists configured versions). |
|
|
28
|
-
| [`blume migrate [source]`](/docs/migrating) | Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with Claude Code
|
|
29
|
-
| [`blume upgrade`](/docs/upgrading) | Move to a new major: bump `blume`, then list the config changes left or hand them to Claude Code
|
|
28
|
+
| [`blume migrate [source]`](/docs/migrating) | Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with Codex or Claude Code. |
|
|
29
|
+
| [`blume upgrade`](/docs/upgrading) | Move to a new major: bump `blume`, then list the config changes left or hand them to Codex or Claude Code. |
|
|
30
30
|
|
|
31
31
|
## Common flags
|
|
32
32
|
|
package/docs/cli/translate.mdx
CHANGED
|
@@ -6,22 +6,22 @@ description: blume translate fills in your locales with an AI agent — it finds
|
|
|
6
6
|
Once [i18n](/docs/content/i18n) is on, every edit to a source page quietly outdates its translations. `blume translate` closes that loop: it computes exactly which pages are missing or stale in each locale, translates them headlessly with a local agent CLI, and records what it did in a committed ledger so the next run — and CI — knows what's current.
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
blume translate --
|
|
9
|
+
blume translate --codex
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
```
|
|
13
|
-
blume translate 3 item(s) · 2 locale(s) ·
|
|
13
|
+
blume translate 3 item(s) · 2 locale(s) · Codex
|
|
14
14
|
|
|
15
|
-
✔ docs/guides/install.mdx → fr 24.2s
|
|
16
|
-
✔ docs/guides/install.mdx → de 22.8s
|
|
17
|
-
✔ meta titles (2) → de 4.1s
|
|
15
|
+
✔ docs/guides/install.mdx → fr 24.2s
|
|
16
|
+
✔ docs/guides/install.mdx → de 22.8s
|
|
17
|
+
✔ meta titles (2) → de 4.1s
|
|
18
18
|
|
|
19
|
-
Translated 3 files into 2 locales · 1 adopted · 14 already up to date · 51.1s
|
|
19
|
+
Translated 3 files into 2 locales · 1 adopted · 14 already up to date · 51.1s
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
## How it works
|
|
23
23
|
|
|
24
|
-
Blume owns the pipeline; the agent only translates text. For each file that needs work, Blume builds a translation prompt, runs the agent CLI headlessly with its file, shell, and web tools disabled, validates the reply's structure, and writes the target file itself — [
|
|
24
|
+
Blume owns the pipeline; the agent only translates text. For each file that needs work, Blume builds a translation prompt, runs the agent CLI headlessly with its file, shell, and web tools disabled, validates the reply's structure, and writes the target file itself — [Codex](https://developers.openai.com/codex/cli) with `--codex`, or [Claude Code](https://claude.com/claude-code) with `--claude`. Blume holds no API keys and calls no model itself.
|
|
25
25
|
|
|
26
26
|
Every validated write is recorded in `blume.translations.json` at the project root: for each source file and locale, a hash of the source at the moment it was translated. **Commit this file.** It's how a rerun knows the difference between "already translated" and "translated, but the source changed since" — and it's what makes the CI gate possible.
|
|
27
27
|
|
|
@@ -72,7 +72,7 @@ The JSON report carries the same `diagnostics` + `summary` shape as `blume valid
|
|
|
72
72
|
|
|
73
73
|
## Flags
|
|
74
74
|
|
|
75
|
-
- `--
|
|
75
|
+
- `--codex` / `--claude` — which agent CLI translates. Exactly one is required (except with `--check`).
|
|
76
76
|
- `--check` — report drift and exit non-zero, without writing anything.
|
|
77
77
|
- `--concurrency <n>` — parallel agent sessions. Defaults to `4`, max `16`.
|
|
78
78
|
- `--locale <codes>` — comma-separated target locales (defaults to every non-default locale).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
2
|
+
title: Assistant
|
|
3
3
|
description: An in-page assistant grounded in your docs — suggested questions, custom instructions, retrieval sizing, provider adapters from the Vercel AI Gateway to any OpenAI-compatible endpoint, and the server output it needs.
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@ Add an assistant that answers reader questions in an in-page chat panel, backed
|
|
|
7
7
|
|
|
8
8
|
```ts blume.config.ts lineNumbers
|
|
9
9
|
ai: {
|
|
10
|
-
|
|
10
|
+
assistant: {
|
|
11
11
|
enabled: true,
|
|
12
12
|
},
|
|
13
13
|
}
|
|
@@ -21,7 +21,7 @@ Seed the empty state with a few starter prompts. Each renders as a clickable sug
|
|
|
21
21
|
|
|
22
22
|
```ts blume.config.ts lineNumbers
|
|
23
23
|
ai: {
|
|
24
|
-
|
|
24
|
+
assistant: {
|
|
25
25
|
enabled: true,
|
|
26
26
|
suggestions: [
|
|
27
27
|
{ label: "What is Blume?", icon: "rocket" },
|
|
@@ -40,7 +40,7 @@ Add your own system-prompt text with `instructions` — identity, language, tone
|
|
|
40
40
|
|
|
41
41
|
```ts blume.config.ts lineNumbers
|
|
42
42
|
ai: {
|
|
43
|
-
|
|
43
|
+
assistant: {
|
|
44
44
|
enabled: true,
|
|
45
45
|
instructions:
|
|
46
46
|
"You are Bloomy, the Acme docs assistant. Answer in the language the question was asked in, and keep answers under three paragraphs.",
|
|
@@ -52,7 +52,7 @@ Your text is **appended to** the built-in instructions rather than replacing the
|
|
|
52
52
|
|
|
53
53
|
## Grounding
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
The assistant is **grounded in your docs**. For each question it retrieves the most relevant pages — using the same lexical [Orama](/docs/configuration/search) index that powers on-page search — and injects them into the model's system prompt, so answers come from your content instead of the model's own knowledge. The assistant is told to answer only from the retrieved pages, to say when something isn't covered, and to cite the pages it drew from.
|
|
56
56
|
|
|
57
57
|
The page the reader is currently on is added to the context first and used to scope retrieval to that page's language, so answers stay relevant to where they are in the docs. Retrieval runs at request time from a snapshot baked into the build, so it works regardless of your [search](/docs/configuration/search) provider — even with `search: false` — and needs no configuration.
|
|
58
58
|
|
|
@@ -64,7 +64,7 @@ How much documentation a question carries is the biggest lever on how long the r
|
|
|
64
64
|
|
|
65
65
|
```ts blume.config.ts lineNumbers
|
|
66
66
|
ai: {
|
|
67
|
-
|
|
67
|
+
assistant: {
|
|
68
68
|
enabled: true,
|
|
69
69
|
retrieval: {
|
|
70
70
|
maxResults: 3, // fewer pages retrieved per question
|
|
@@ -91,7 +91,7 @@ Already have an API backend for AI? Point the panel at it and keep the docs buil
|
|
|
91
91
|
|
|
92
92
|
```ts blume.config.ts lineNumbers
|
|
93
93
|
ai: {
|
|
94
|
-
|
|
94
|
+
assistant: {
|
|
95
95
|
enabled: true,
|
|
96
96
|
endpoint: "https://api.example.com/v1/docs/ask",
|
|
97
97
|
},
|
|
@@ -115,7 +115,7 @@ The generated endpoint answers the in-page assistant on its own origin. To call
|
|
|
115
115
|
|
|
116
116
|
```ts blume.config.ts lineNumbers
|
|
117
117
|
ai: {
|
|
118
|
-
|
|
118
|
+
assistant: {
|
|
119
119
|
enabled: true,
|
|
120
120
|
cors: ["https://www.example.com"],
|
|
121
121
|
},
|
|
@@ -142,7 +142,7 @@ The content type matters: Astro's cross-site request check rejects a cross-origi
|
|
|
142
142
|
|
|
143
143
|
## Server output required
|
|
144
144
|
|
|
145
|
-
Blume's built-in
|
|
145
|
+
Blume's built-in assistant backend is a server route (`POST /api/ask`), so it can't run on a static build. Name a host adapter from `blume/deploy` to switch to server output:
|
|
146
146
|
|
|
147
147
|
```ts blume.config.ts lineNumbers
|
|
148
148
|
import { vercel } from "blume/deploy";
|
|
@@ -152,7 +152,7 @@ export default defineConfig({
|
|
|
152
152
|
});
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
A static build with
|
|
155
|
+
A static build with the assistant enabled and no external `endpoint` fails fast with a message telling you to set a host adapter. See [Deployment](/docs/deployment) for the adapters.
|
|
156
156
|
|
|
157
157
|
## Adapters
|
|
158
158
|
|
|
@@ -164,7 +164,7 @@ import { openrouter } from "blume/ai";
|
|
|
164
164
|
|
|
165
165
|
export default defineConfig({
|
|
166
166
|
ai: {
|
|
167
|
-
|
|
167
|
+
assistant: {
|
|
168
168
|
enabled: true,
|
|
169
169
|
provider: openrouter({ model: "anthropic/claude-sonnet-4-5" }),
|
|
170
170
|
},
|
|
@@ -194,7 +194,7 @@ import { gateway } from "blume/ai";
|
|
|
194
194
|
|
|
195
195
|
export default defineConfig({
|
|
196
196
|
ai: {
|
|
197
|
-
|
|
197
|
+
assistant: {
|
|
198
198
|
enabled: true,
|
|
199
199
|
provider: gateway({ model: "anthropic/claude-sonnet-4-5" }),
|
|
200
200
|
},
|
|
@@ -214,7 +214,7 @@ import { openrouter } from "blume/ai";
|
|
|
214
214
|
|
|
215
215
|
export default defineConfig({
|
|
216
216
|
ai: {
|
|
217
|
-
|
|
217
|
+
assistant: {
|
|
218
218
|
enabled: true,
|
|
219
219
|
provider: openrouter({
|
|
220
220
|
model: "anthropic/claude-sonnet-4-5",
|
|
@@ -235,7 +235,7 @@ import { llmgateway } from "blume/ai";
|
|
|
235
235
|
|
|
236
236
|
export default defineConfig({
|
|
237
237
|
ai: {
|
|
238
|
-
|
|
238
|
+
assistant: {
|
|
239
239
|
enabled: true,
|
|
240
240
|
provider: llmgateway({ model: "openai/gpt-5.5" }),
|
|
241
241
|
},
|
|
@@ -255,7 +255,7 @@ import { inkeep } from "blume/ai";
|
|
|
255
255
|
|
|
256
256
|
export default defineConfig({
|
|
257
257
|
ai: {
|
|
258
|
-
|
|
258
|
+
assistant: {
|
|
259
259
|
enabled: true,
|
|
260
260
|
provider: inkeep({ model: "inkeep-qa-expert" }),
|
|
261
261
|
},
|
|
@@ -275,7 +275,7 @@ import { openaiCompatible } from "blume/ai";
|
|
|
275
275
|
|
|
276
276
|
export default defineConfig({
|
|
277
277
|
ai: {
|
|
278
|
-
|
|
278
|
+
assistant: {
|
|
279
279
|
enabled: true,
|
|
280
280
|
provider: openaiCompatible({
|
|
281
281
|
baseUrl: "https://my-gateway.example.com/v1",
|
|
@@ -314,7 +314,7 @@ provider: gateway({
|
|
|
314
314
|
}),
|
|
315
315
|
```
|
|
316
316
|
|
|
317
|
-
Blume maps only the options it names (`model`, `reasoning`, `apiKeyEnv`, `headers`) and forwards `providerOptions` verbatim, so it has to be JSON — it's inlined into the route — and it has to use the key the underlying provider expects (`openai` for an OpenAI model behind the gateway, `openrouter` on OpenRouter). Enabling
|
|
317
|
+
Blume maps only the options it names (`model`, `reasoning`, `apiKeyEnv`, `headers`) and forwards `providerOptions` verbatim, so it has to be JSON — it's inlined into the route — and it has to use the key the underlying provider expects (`openai` for an OpenAI model behind the gateway, `openrouter` on OpenRouter). Enabling the assistant also turns on React for the in-page island — see [Customization](/docs/configuration/customization#interactive-islands).
|
|
318
318
|
|
|
319
319
|
## Reasoning
|
|
320
320
|
|
|
@@ -324,7 +324,7 @@ Reasoning models think before they answer, and how much they do so by default va
|
|
|
324
324
|
provider: gateway({ model: "openai/gpt-5.5", reasoning: "none" }),
|
|
325
325
|
```
|
|
326
326
|
|
|
327
|
-
Each adapter sends the level as its backend's own reasoning control, which is why it lives on the adapter rather than on `
|
|
327
|
+
Each adapter sends the level as its backend's own reasoning control, which is why it lives on the adapter rather than on `assistant`:
|
|
328
328
|
|
|
329
329
|
| Adapter | What the level becomes |
|
|
330
330
|
| --- | --- |
|
|
@@ -348,7 +348,7 @@ With an [analytics provider](/docs/configuration/analytics) configured, the assi
|
|
|
348
348
|
|
|
349
349
|
`path` is the page the reader asked from (the served pathname, so it matches the feedback widget and your pageviews under a `base`), `questionChars` the question's length, `ms` the time from sending the question to the last chunk, and `chars` the answer's length. `status` is the HTTP status: `0` when no response arrived at all (offline, DNS, CORS), and `200` when the response was fine but its stream broke mid-answer — how a provider or credential error surfaces, since the backend has already sent its headers — or delivered nothing. Clearing the conversation mid-answer reports neither outcome.
|
|
350
350
|
|
|
351
|
-
The question's text never reaches a provider: it is free-form reader input (pasted keys, error logs, names) that would breach most providers' terms and per-value size limits. It travels only on the `blume:track` DOM event, as `question` in `detail.props`, so a listener you write can forward it wherever you decide it belongs. A custom chat UI built on `
|
|
351
|
+
The question's text never reaches a provider: it is free-form reader input (pasted keys, error logs, names) that would breach most providers' terms and per-value size limits. It travels only on the `blume:track` DOM event, as `question` in `detail.props`, so a listener you write can forward it wherever you decide it belongs. A custom chat UI built on `useAssistant` from `blume/hooks` reports the same events. With no provider configured the built-in provider calls are no-ops, but the `blume:track` event still fires, so a custom integration listening for it receives them.
|
|
352
352
|
|
|
353
353
|
## Rate limiting
|
|
354
354
|
|
|
@@ -91,7 +91,7 @@ Wired slots:
|
|
|
91
91
|
| `Layout` | The entire page shell (`RootLayout`) | Everything the built-in layout receives, plus the `layout` map |
|
|
92
92
|
| `Header` | The top navigation bar | `site`, `logo`, `navigation`, `route`, `searchEnabled`, … |
|
|
93
93
|
| `Logo` | The brand link (mark + title) in the header | `site`, `logo`, `locale` |
|
|
94
|
-
| `Search` | The header search trigger + modal | `navigation`, `strings`, `locale`, `
|
|
94
|
+
| `Search` | The header search trigger + modal | `navigation`, `strings`, `locale`, `assistantEnabled` |
|
|
95
95
|
| `Sidebar` | The primary navigation tree | `items`, `currentRoute` |
|
|
96
96
|
| `MobileNav` | The nav inside the mobile drawer (defaults to `Sidebar`) | `items`, `currentRoute` |
|
|
97
97
|
| `Breadcrumbs` | The breadcrumb trail | `crumbs` |
|
|
@@ -184,7 +184,7 @@ npx blume eject --yes
|
|
|
184
184
|
|
|
185
185
|
Eject is a one-way step: the hidden `.blume/` runtime becomes a normal Astro app you own and can modify directly. The `blume` package stays importable, so you keep its components, theme, and Markdown processors.
|
|
186
186
|
|
|
187
|
-
Eject points your `package.json` scripts at `astro dev` and `astro build`, and adds the packages the Astro app imports by name — `astro`, `@tailwindcss/vite`, the search client, integrations, and adapter the config wires in, React when an island, example, or
|
|
187
|
+
Eject points your `package.json` scripts at `astro dev` and `astro build`, and adds the packages the Astro app imports by name — `astro`, `@tailwindcss/vite`, the search client, integrations, and adapter the config wires in, React when an island, example, or the assistant uses it, `ai` for the assistant route, and `epub-gen-memory` for EPUB export — at the ranges Blume itself uses. Run an install before `dev` or `build`; eject lists what it added. Every path in the ejected app is relative, so it builds from any checkout, CI included.
|
|
188
188
|
|
|
189
189
|
From then on, run the app through its own scripts (`npm run dev`, `npm run build`): `blume dev` and `blume build` stop in an ejected project and point you there. Running `blume eject` again refuses too, since it would overwrite your edits; pass `--force` to regenerate the app anyway.
|
|
190
190
|
|
|
@@ -366,7 +366,7 @@ dateFormat: { year: "numeric", month: "2-digit", day: "2-digit" },
|
|
|
366
366
|
|
|
367
367
|
## SEO and agents
|
|
368
368
|
|
|
369
|
-
Metadata, Open Graph images, RSS feeds, JSON-LD, the sitemap, and `robots.txt` live under `seo`; `llms.txt`, raw Markdown, the JSON API, the MCP server, and the discovery manifests live under `agents`. Both are covered page by page in the [Discoverability](/docs/discoverability) section, which treats search engines and AI agents as two audiences for the same machine-readable layer. The reader-facing model features — the
|
|
369
|
+
Metadata, Open Graph images, RSS feeds, JSON-LD, the sitemap, and `robots.txt` live under `seo`; `llms.txt`, raw Markdown, the JSON API, the MCP server, and the discovery manifests live under `agents`. Both are covered page by page in the [Discoverability](/docs/discoverability) section, which treats search engines and AI agents as two audiences for the same machine-readable layer. The reader-facing model features — the assistant and the Open in chat action — live under `ai`.
|
|
370
370
|
|
|
371
371
|
```ts blume.config.ts lineNumbers
|
|
372
372
|
seo: {
|
|
@@ -431,7 +431,7 @@ Each of these has its own guide. The config field is the entry point:
|
|
|
431
431
|
| `search` | Provider (Orama, Pagefind, Algolia, and more) and indexing | [Search](/docs/configuration/search) |
|
|
432
432
|
| `markdown` | Markdown rendering options — code blocks, heading anchors, image zoom | [Syntax](/docs/content/syntax) |
|
|
433
433
|
| `agents` | `llms.txt`, Markdown mirrors, the JSON API, the hosted MCP server, skills, and discovery manifests for coding agents | [SEO and AEO](/docs/discoverability) |
|
|
434
|
-
| `ai` | The in-page
|
|
434
|
+
| `ai` | The in-page assistant and the Open in chat action | [Assistant](/docs/configuration/assistant) |
|
|
435
435
|
| `reference` | API references: `openapi()`, `asyncapi()`, `graphql()`, and `scalar()` adapters from `blume/reference` | [OpenAPI](/docs/references/openapi), [AsyncAPI](/docs/references/asyncapi), [GraphQL](/docs/references/graphql), [Scalar](/docs/references/scalar) |
|
|
436
436
|
| `analytics` | Adapters from `blume/analytics` — PostHog, Google Analytics, Plausible, Mixpanel, Segment, and more — plus custom scripts | [Analytics](/docs/configuration/analytics) |
|
|
437
437
|
| `seo` | Metadata, OG images, feeds, structured data, sitemap, robots | [SEO and AEO](/docs/discoverability) |
|
|
@@ -115,7 +115,7 @@ i18n: {
|
|
|
115
115
|
}
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
The same tokenizer serves the search dialog, the MCP server's `search_docs` tool, and
|
|
118
|
+
The same tokenizer serves the search dialog, the MCP server's `search_docs` tool, and assistant grounding. The script is what decides, not the language name — `az-Cyrl` is segmented while `sr-Latn` is not — and it is the default locale that decides for the whole index: on a mixed-language site every page shares the default locale's tokenizer. With a non-Latin default that's safe, because Latin words survive segmentation intact, so pages in English stay searchable alongside the default language. The reverse doesn't hold: non-Latin translations on a Latin-default site aren't searchable. Latin-script languages that lean heavily on diacritics (Vietnamese, or Serbian in Latin script) also fare worse on the standard tokenizer, which folds only a few accented vowels and splits words on the rest.
|
|
119
119
|
|
|
120
120
|
Japanese and Chinese go one step further. Segmenting alone indexes a compound term as its parts — 資金決済法 as 資金, 決済 and 法 — which lets a page mentioning each part somewhere outrank the page the term is actually about. Han, Hiragana and Katakana are therefore indexed as overlapping character pairs, and queries on those indexes prefer pages carrying a term's pairs together, loosening to any-pair matching when no page carries them all, so typing a whole sentence still returns its closest pages. Korean and Thai keep their segmented words.
|
|
121
121
|
|
package/docs/content/i18n.mdx
CHANGED
|
@@ -112,10 +112,10 @@ Anchors travel with the link, so heading ids have to agree across languages. [`b
|
|
|
112
112
|
|
|
113
113
|
## Translating with an agent
|
|
114
114
|
|
|
115
|
-
You don't have to fill in the locales by hand. [`blume translate`](/docs/cli/translate) finds every page that's missing or outdated in each locale and translates it with a local agent CLI ([
|
|
115
|
+
You don't have to fill in the locales by hand. [`blume translate`](/docs/cli/translate) finds every page that's missing or outdated in each locale and translates it with a local agent CLI ([Codex](https://developers.openai.com/codex/cli) or [Claude Code](https://claude.com/claude-code)):
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
blume translate --
|
|
118
|
+
blume translate --codex
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
Blume validates each result's structure — frontmatter, code fences, links — and writes the files itself; the agent only translates text. A committed ledger (`blume.translations.json`) tracks which source revision each translation came from, so reruns only touch what changed, and translations you wrote by hand are adopted as-is, never overwritten. In CI, `blume translate --check` fails when a source page has drifted ahead of its translations.
|
package/docs/content/islands.mdx
CHANGED
|
@@ -143,7 +143,7 @@ export default function PageInfo() {
|
|
|
143
143
|
| `useBlume()` | `{ config, navigation }` for the site, or `null` before mount |
|
|
144
144
|
| `usePage()` | `{ route, title }` for the current page, or `null` before mount |
|
|
145
145
|
| `useSearch()` | `{ search, results, loading }` — query the configured search provider |
|
|
146
|
-
| `
|
|
146
|
+
| `useAssistant()` | `{ ask, messages, loading, reset }` — stream from the assistant endpoint |
|
|
147
147
|
|
|
148
148
|
`useBlume()` and `usePage()` return `null` until the island mounts (so server and client render the same first frame) — guard for it. The snapshot is emitted only on pages that ship React, so a fully static site pays nothing.
|
|
149
149
|
|
|
@@ -15,7 +15,7 @@ agents: {
|
|
|
15
15
|
}
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
The manifest lists only what you've enabled — the [raw Markdown](/docs/discoverability/markdown) mirror pattern, the [JSON API](/docs/discoverability/json-api) and its OpenAPI description, [`llms.txt`](/docs/discoverability/llms-txt) and `llms-full.txt`, the [MCP server](/docs/discoverability/mcp) and its discovery document, the [
|
|
18
|
+
The manifest lists only what you've enabled — the [raw Markdown](/docs/discoverability/markdown) mirror pattern, the [JSON API](/docs/discoverability/json-api) and its OpenAPI description, [`llms.txt`](/docs/discoverability/llms-txt) and `llms-full.txt`, the [MCP server](/docs/discoverability/mcp) and its discovery document, the [assistant](/docs/configuration/assistant) endpoint, the [sitemap](/docs/discoverability/sitemap-and-robots#sitemap), and [RSS feeds](/docs/discoverability/rss) — alongside your site name, description, source repository, and the [content-signal](/docs/discoverability/sitemap-and-robots#content-signals) usage policy. URLs are absolute when [`deployment.site`](/docs/deployment) is set and root-relative otherwise:
|
|
19
19
|
|
|
20
20
|
```json agent-readability.json
|
|
21
21
|
{
|
|
@@ -41,7 +41,7 @@ Most of this is sharper with an absolute site URL — set [`deployment.site`](/d
|
|
|
41
41
|
|
|
42
42
|
Every generated file yields to one you ship yourself: drop a `robots.txt`, `sitemap.xml`, `llms.txt`, `openapi.json`, or `agent-readability.json` in `public/` and Blume serves yours in its place.
|
|
43
43
|
|
|
44
|
-
The in-page **
|
|
44
|
+
The in-page **assistant** is the one AI feature documented elsewhere: it's a reader-facing product feature rather than a discovery surface, so it's configured under `ai` and lives under [Configuration](/docs/configuration/assistant).
|
|
45
45
|
|
|
46
46
|
## Checking your work
|
|
47
47
|
|
package/docs/index.mdx
CHANGED
|
@@ -31,7 +31,7 @@ Blume builds on Astro and Vite and renders static HTML by default — fast, cach
|
|
|
31
31
|
|
|
32
32
|
### AI-ready out of the box
|
|
33
33
|
|
|
34
|
-
Every Blume site speaks fluent machine. It emits [`llms.txt` and `llms-full.txt`](/docs/discoverability/llms-txt), serves any page's raw Markdown by appending `.md` to its URL, exposes a [JSON API described by OpenAPI](/docs/discoverability/json-api), and gives readers **Copy as Markdown** and **Open in chat** actions on every page. Add an optional in-page **
|
|
34
|
+
Every Blume site speaks fluent machine. It emits [`llms.txt` and `llms-full.txt`](/docs/discoverability/llms-txt), serves any page's raw Markdown by appending `.md` to its URL, exposes a [JSON API described by OpenAPI](/docs/discoverability/json-api), and gives readers **Copy as Markdown** and **Open in chat** actions on every page. Add an optional in-page **assistant**, or host an [**MCP server**](/docs/discoverability/mcp) so coding agents like Claude Code and Cursor can search and read your docs directly — no scraping, no hosted service. Your Markdown is the source of truth for both humans and models.
|
|
35
35
|
|
|
36
36
|
### Zero configuration — even the template
|
|
37
37
|
|
|
@@ -45,7 +45,7 @@ Your [`blume.config.ts`](/docs/configuration) and every [`meta.ts`](/docs/conten
|
|
|
45
45
|
|
|
46
46
|
- **Components** — callouts, cards, steps, tabs, accordions, badges, file trees, and parameter tables, usable in MDX with [no imports](/docs/content/components).
|
|
47
47
|
- **Local search** — Orama works in dev and production; for large sites, Pagefind is one adapter away (`search: pagefind()`). No hosted index.
|
|
48
|
-
- **AI** — [`llms.txt`, raw Markdown URLs, a JSON API with an OpenAPI description, Copy as Markdown, Open in chat, and a hosted MCP server](/docs/discoverability), plus an optional [
|
|
48
|
+
- **AI** — [`llms.txt`, raw Markdown URLs, a JSON API with an OpenAPI description, Copy as Markdown, Open in chat, and a hosted MCP server](/docs/discoverability), plus an optional [in-page assistant](/docs/configuration/assistant).
|
|
49
49
|
- **Navigation** — inferred from files, refined with `meta.ts` or config.
|
|
50
50
|
- **SEO** — metadata, Open Graph images, RSS feeds, and JSON-LD, [built in](/docs/discoverability).
|
|
51
51
|
- **Customization** — component overrides, React islands, custom pages, theme tokens, and a source-component registry via `blume add`.
|