blume 0.7.0 → 0.8.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 +618 -0
- package/LICENSE +21 -0
- package/README.md +107 -0
- package/dist/cli/index.js +1487 -360
- package/dist/cli/index.js.map +91 -85
- package/dist/types/ai/component-markdown.d.ts +34 -0
- package/dist/types/components/content/youtube.d.ts +18 -0
- package/dist/types/core/base-path.d.ts +9 -0
- package/dist/types/core/config-input.d.ts +36 -2
- package/dist/types/core/config.d.ts +3 -2
- package/dist/types/core/data.d.ts +2 -0
- package/dist/types/core/i18n-ui.d.ts +476 -132
- package/dist/types/core/schema.d.ts +216 -145
- package/dist/types/index.d.ts +1 -0
- package/dist/types/openapi/references.d.ts +60 -0
- package/docs/01-quickstart.mdx +5 -2
- package/docs/02-deployment.mdx +8 -8
- package/docs/03-faq.mdx +46 -16
- package/docs/advanced/custom-pages.mdx +1 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/configuration/ai.mdx +49 -10
- package/docs/configuration/customization.mdx +11 -0
- package/docs/configuration/index.mdx +27 -3
- package/docs/configuration/seo.mdx +2 -2
- package/docs/content/components.mdx +1 -1
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/navigation.mdx +3 -3
- package/docs/content/sources.mdx +1 -1
- package/docs/content/syntax.mdx +4 -2
- package/docs/index.mdx +2 -2
- package/docs/reference/cli.mdx +8 -6
- package/package.json +14 -4
- package/skills/blume/SKILL.md +5 -3
- package/skills/blume-update-docs/SKILL.md +3 -2
- package/src/ai/agent-readability.ts +9 -8
- package/src/ai/ask-context.ts +7 -2
- package/src/ai/ask-data.ts +3 -0
- package/src/ai/component-markdown.ts +461 -0
- package/src/ai/llms.ts +135 -26
- package/src/ai/markdown.ts +35 -6
- package/src/ai/mcp/data.ts +25 -4
- package/src/ai/mcp/discovery.ts +10 -3
- package/src/ai/mcp/server.ts +21 -7
- package/src/ai/visibility.ts +74 -0
- package/src/astro/component-slots.ts +11 -1
- package/src/astro/generate.ts +76 -45
- package/src/astro/integration.ts +1 -1
- package/src/astro/markdown-negotiation.ts +1 -1
- package/src/astro/pages.ts +81 -19
- package/src/astro/templates.ts +99 -12
- package/src/blume-modules.d.ts +8 -0
- package/src/cli/commands/build.ts +99 -19
- package/src/cli/commands/check.ts +1 -1
- package/src/cli/commands/dev.ts +26 -5
- package/src/cli/commands/eject.ts +47 -19
- package/src/cli/commands/init.ts +120 -180
- package/src/cli/commands/preview.ts +4 -1
- package/src/cli/commands/validate.ts +43 -2
- package/src/cli/dev-lock.ts +8 -4
- package/src/cli/eject-scripts.ts +72 -0
- package/src/cli/env.ts +15 -5
- package/src/cli/init/questions.ts +158 -0
- package/src/cli/init/scaffold.ts +380 -0
- package/src/components/content/AccordionItem.astro +23 -4
- package/src/components/content/Badge.astro +3 -1
- package/src/components/content/Card.astro +4 -2
- package/src/components/content/Step.astro +10 -1
- package/src/components/content/Tabs.astro +15 -3
- package/src/components/content/Tile.astro +2 -1
- package/src/components/content/Tooltip.astro +3 -1
- package/src/components/content/Update.astro +9 -2
- package/src/components/content/auto-type-table.ts +7 -1
- package/src/components/content/base-href.ts +33 -0
- package/src/components/content/changelog-element.ts +9 -2
- package/src/components/content/mermaid-element.ts +7 -2
- package/src/components/islands/AskAI.astro +5 -2
- package/src/components/islands/ask-ai.tsx +56 -6
- package/src/components/islands/hooks.ts +28 -8
- package/src/components/layout/Banner.astro +10 -2
- package/src/components/layout/Header.astro +13 -4
- package/src/components/layout/Logo.astro +11 -3
- package/src/components/layout/NavTree.astro +17 -3
- package/src/components/layout/PageActions.astro +25 -10
- package/src/components/layout/PageLayout.astro +45 -8
- package/src/components/layout/ReferenceLayout.astro +8 -1
- package/src/components/layout/RootLayout.astro +67 -9
- package/src/components/layout/Search.astro +94 -22
- package/src/components/layout/search/algolia.ts +11 -2
- package/src/components/layout/search/endpoint.ts +11 -5
- package/src/components/layout/search/orama-cloud.ts +8 -2
- package/src/components/layout/search/types.ts +5 -1
- package/src/components/layout/search/typesense.ts +4 -1
- package/src/components/layout/toc-element.ts +1 -1
- package/src/components/openapi/ApiTagOperations.astro +2 -1
- package/src/components/openapi/Operation.astro +47 -40
- package/src/components/openapi/RequestPanel.astro +1 -1
- package/src/components/openapi/helpers.ts +71 -3
- package/src/components/openapi/panel.ts +1 -1
- package/src/core/base-path.ts +24 -0
- package/src/core/builtin-tags.ts +2 -0
- package/src/core/config-input.ts +37 -2
- package/src/core/config.ts +3 -2
- package/src/core/data.ts +2 -0
- package/src/core/graph.ts +15 -5
- package/src/core/i18n-ui.ts +45 -0
- package/src/core/last-modified.ts +13 -6
- package/src/core/links.ts +32 -8
- package/src/core/navigation.ts +29 -4
- package/src/core/package-json.ts +17 -2
- package/src/core/project-graph.ts +15 -6
- package/src/core/schema.ts +36 -2
- package/src/core/sources/assets.ts +6 -1
- package/src/core/sources/filesystem.ts +4 -0
- package/src/core/sources/mdx-remote.ts +23 -14
- package/src/core/sources/normalize.ts +152 -50
- package/src/core/sources/notion.ts +8 -8
- package/src/core/ui-packs/ar.ts +1 -0
- package/src/core/ui-packs/bg.ts +1 -0
- package/src/core/ui-packs/bn.ts +1 -0
- package/src/core/ui-packs/ca.ts +1 -0
- package/src/core/ui-packs/cs.ts +1 -0
- package/src/core/ui-packs/da.ts +1 -0
- package/src/core/ui-packs/de.ts +1 -0
- package/src/core/ui-packs/el.ts +1 -0
- package/src/core/ui-packs/es.ts +1 -0
- package/src/core/ui-packs/fa.ts +1 -0
- package/src/core/ui-packs/fi.ts +1 -0
- package/src/core/ui-packs/fr.ts +2 -1
- package/src/core/ui-packs/he.ts +1 -0
- package/src/core/ui-packs/hi.ts +1 -0
- package/src/core/ui-packs/hr.ts +1 -0
- package/src/core/ui-packs/hu.ts +1 -0
- package/src/core/ui-packs/id.ts +1 -0
- package/src/core/ui-packs/it.ts +1 -0
- package/src/core/ui-packs/ja.ts +1 -0
- package/src/core/ui-packs/ko.ts +1 -0
- package/src/core/ui-packs/nl.ts +1 -0
- package/src/core/ui-packs/no.ts +1 -0
- package/src/core/ui-packs/pl.ts +1 -0
- package/src/core/ui-packs/pt-br.ts +1 -0
- package/src/core/ui-packs/pt.ts +1 -0
- package/src/core/ui-packs/ro.ts +1 -0
- package/src/core/ui-packs/ru.ts +1 -0
- package/src/core/ui-packs/sk.ts +1 -0
- package/src/core/ui-packs/sr.ts +1 -0
- package/src/core/ui-packs/sv.ts +1 -0
- package/src/core/ui-packs/th.ts +1 -0
- package/src/core/ui-packs/tr.ts +1 -0
- package/src/core/ui-packs/uk.ts +1 -0
- package/src/core/ui-packs/vi.ts +1 -0
- package/src/core/ui-packs/zh-tw.ts +1 -0
- package/src/core/ui-packs/zh.ts +1 -0
- package/src/deploy/adapter-output.ts +18 -8
- package/src/deploy/redirects.ts +7 -2
- package/src/deploy/sitemap.ts +53 -11
- package/src/index.ts +5 -0
- package/src/markdown/base-links.ts +10 -8
- package/src/markdown/index.ts +15 -3
- package/src/markdown/inline-code.ts +7 -2
- package/src/markdown/package-commands.ts +10 -4
- package/src/openapi/model.ts +12 -4
- package/src/openapi/parse.ts +21 -0
- package/src/openapi/references.ts +38 -8
- package/src/openapi/source.ts +59 -10
- package/src/registry/eject.ts +184 -12
- package/src/registry/registry.ts +0 -3
- package/src/search/documents.ts +34 -2
- package/src/seo/jsonld.ts +13 -12
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
# blume
|
|
2
|
+
|
|
3
|
+
## 0.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 89b5685: The `.md` raw-Markdown mirror now downlevels components to plain Markdown for agent consumers: `<TypeTable>` becomes a GFM table, `<Callout>` a labeled blockquote, `<Steps>` an ordered list, `<Tabs>` bold-labeled sections, and `<YouTube>` a link. The `.mdx` mirror keeps serving the source exactly as written, so both audiences get what the extension implies. The same conversion applies to `llms-full.txt` and the MCP server's `get_page` tool. Unknown components, props that can't be recovered statically, and component markup inside fenced code blocks are all left verbatim.
|
|
8
|
+
|
|
9
|
+
Custom components can join in via `ai.markdownComponents` in `blume.config.ts`: a map of JSX name to `ComponentMarkdown` serializer, receiving the statically-evaluated props and downleveled children. A same-name entry replaces a built-in serializer.
|
|
10
|
+
|
|
11
|
+
- 1fd8368: `blume init` is now interactive: in a terminal it asks where to create the project (also available as `blume init <dir>`), what your docs site is called, which template to use, and which content sources you need (filesystem, GitHub Releases, Notion, Sanity, remote MDX), then scaffolds a matching `blume.config.ts` — including a `content.sources` block with placeholder values, env-var hints, and the Notion/Sanity SDK dependencies when those sources are picked. Explicit flags pre-answer their prompts; `--yes`, CI, or piped stdio keep the previous non-interactive behavior with identical default output. The package manager for next-steps hints is auto-detected from `npm_config_user_agent`, and a non-default `--content-dir` now also emits `content.root` so the scaffolded project reads the right folder.
|
|
12
|
+
- 8161706: `llms.txt` now mirrors your navigation tree instead of emitting one flat list: sidebar folders and groups become Markdown headings (nested groups nest the heading level), each locale gets its own labeled section under i18n, and pages an explicit sidebar omits are appended under "Other". `ai.llmsTxt` also accepts an object form — `{ enabled, openapi }` — where `openapi: false` keeps generated API reference pages (OpenAPI/AsyncAPI) out of both `llms.txt` and `llms-full.txt`, for sites whose reference documents a placeholder or example spec. The bare boolean shorthand keeps working.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 21aa451: API overview operation cards now link to the operation pages' routes under the site-wide `basePath`, matching where the content pipeline actually mounts them, so the cards no longer 404 when a `basePath` is configured.
|
|
17
|
+
- 759b148: API overview operation links now route through `withBase`, so they resolve under `deployment.base` like the sidebar and header links to the same pages.
|
|
18
|
+
- 759b148: Ask AI citation links now resolve under `deployment.base`: the rendered answer prefixes root-relative routes with the base, so citations point at the pages' real served URLs.
|
|
19
|
+
- 559024b: Ask AI grounding excerpts now always contain the matched query term: when the remaining context budget shrinks the excerpt window below the 160-character lead-in, the lead-in is capped so the window no longer ends before the match and injects an irrelevant snippet.
|
|
20
|
+
- 559024b: The generated Ask AI endpoint now rejects a missing API key (or missing AI Gateway credential) up front with a real 500 and a pointer to the env var to set, and logs provider errors server-side via streamText's `onError` callback. Previously `streamText` deferred auth failures to stream consumption, so the endpoint returned a 200 whose stream aborted mid-flight, the UI showed a generic error, and nothing was logged.
|
|
21
|
+
- 759b148: The closed Ask AI panel is now `inert`, so its buttons and textarea no longer sit in the keyboard tab order on every page, and closing the panel returns focus to the element that opened it.
|
|
22
|
+
- 7cda9bf: Opening Ask AI on a "bare" layout page (the changelog index) forced the docs sidebar grid tracks onto its single-column grid, squeezing the whole page into the 17.5rem sidebar track on desktop. The column override now only applies to grids that actually have a TOC column, so bare pages just shrink to make room for the panel like every other layout.
|
|
23
|
+
- 559024b: `<AutoTypeTable>` now reads optionality from the checker's symbol instead of the declaration's question token, so mapped and utility types document correctly: `Partial<Base>` properties render as optional and `Required<Base>` properties as required.
|
|
24
|
+
- 759b148: `<Badge color>` with a 3- or 4-digit hex (e.g. `#f00`) now renders a valid background: the alpha is applied with `color-mix` instead of appending a hex alpha byte.
|
|
25
|
+
- 7cda9bf: The announcement banner rendered by `PageLayout` and `ReferenceLayout` fell back to the English "Dismiss announcement" label even on localized sites — only `RootLayout` passed the UI dictionary through. Both layouts now forward the localized banner strings (`ReferenceLayout` gained the same optional `ui` prop the other layouts have, and the generated Scalar reference page passes the resolved dictionary through).
|
|
26
|
+
- 21aa451: BreadcrumbList JSON-LD now passes Google's Rich Results validation on nested pages. Sidebar groups without an index page used to be emitted as link-less ListItems, which Google rejects on every position except the last; those crumbs are now skipped (with positions renumbered), and the list is omitted when fewer than two linked crumbs remain.
|
|
27
|
+
- 7cda9bf: Corrected a stale comment in `scripts/bundle-docs.mjs`: the script runs on the repo root's `prepare` and the package's `prepack` — the package itself defines no `prepare` script.
|
|
28
|
+
- 7cda9bf: A `deployment.site` with a trailing slash (`https://docs.example.com/`) produced double-slash canonical and `og:image` URLs on pages rendered through `PageLayout` (custom pages, the default 404). The trailing slash is now stripped before joining, matching how content pages build theirs.
|
|
29
|
+
- 759b148: The changelog index's canonical URL now carries `deployment.base` (`site + base + /changelog`), matching how content pages canonicalize.
|
|
30
|
+
- 7cda9bf: Changelog timeline heading links now resolve under `deployment.base`: `<Update>` routes its heading href through `withBase` at emit time, like every other link emitter, so with a base of `/docs` the headings point at `/docs/changelog/vX` instead of 404ing at `/changelog/vX`. In-page anchor fallbacks (`#id`) and external URLs pass through untouched.
|
|
31
|
+
- 7cda9bf: The generated changelog index now passes the resolved UI dictionary and the default locale's lang/dir to the layout, and the generated 404 page now passes lang/dir alongside the dictionary it already used. Previously every chrome string on `/changelog` reverted to English on a non-English default locale, and both pages rendered `dir="ltr"` under an RTL default locale.
|
|
32
|
+
- 7cda9bf: Changelog entries whose labels slug identically (e.g. repeated titles, or several entries with neither a title nor a version) no longer render duplicate element ids: later duplicates are suffixed `-2`, `-3`, ... at build time, so each heading and TOC item deep-links to its own entry instead of the first match. The first occurrence keeps the plain slug, so existing anchors stay stable.
|
|
33
|
+
- 759b148: Closed mobile nav drawers are now `inert` and `aria-hidden`, so their links drop out of the keyboard tab order while closed; the docs sidebar stays fully interactive at desktop widths where it becomes a static column.
|
|
34
|
+
- 6d412dc: Rebase `<Card href>`, `<Tile href>`, `<Tooltip href>`, and `<Card img>` under the served URL. Markdown links are rewritten to the composed `deployment.base` + `basePath` at build, but these component props were emitted raw — so on a GitHub Pages project site (or any `deployment.base`/`basePath` deploy), `<Card href="/quickstart">` linked to a base-less path and 404'd while the adjacent `[x](/quickstart)` worked. Component hrefs now follow the same "write links as if mounted at root" contract as markdown links (idempotent per layer, inert for external URLs, fragments, relative paths, and asset links), `<Card img>` gains the deployment base like every other `public/` asset emitter, and `<Update>` — which previously applied only the deployment base — composes `basePath` too. The site-wide `basePath` is now exposed on `blume:data` as `config.basePath` for custom pages that need the same treatment.
|
|
35
|
+
- 759b148: Content links that hand-write the site-wide `basePath` (`[x](/docs/guide)`) are no longer double-prefixed when `deployment.base` is also set: the markdown link rewriter now layers the two bases separately, so the link resolves to `/base/docs/guide` instead of `/base/docs/docs/guide`.
|
|
36
|
+
- 21aa451: Example generation now honors `const` schemas (the OpenAPI 3.1 discriminator idiom), so `{ type: "string", const: "dog" }` renders `"dog"` in request/response examples instead of the `"string"` placeholder.
|
|
37
|
+
- 759b148: "Copy as Markdown" now checks the fetch response before writing to the clipboard, so a failed request no longer copies an error page and flashes "Copied!".
|
|
38
|
+
- 537d768: A custom `llms.txt` or `llms-full.txt` in your `public/` folder now replaces the generated file, matching the existing sitemap.xml and robots.txt override convention.
|
|
39
|
+
- 7cda9bf: A bare `--host` on `blume dev` and `blume preview` now binds all network interfaces, matching Astro's own flag semantics. Previously the valueless flag parsed as an empty string, which Vite treated as a literal hostname and printed malformed URLs like `http://:4321/`. An explicit `--host 10.0.0.1` still binds that address.
|
|
40
|
+
- 21aa451: The refusal printed when a command would corrupt a running `blume dev` server's `.blume` runtime now only suggests re-running with `--isolated` for commands that actually support the flag (`build` and `check`). `blume eject` now gets accurate advice instead of a flag it silently ignores.
|
|
41
|
+
- 21aa451: Content and config errors introduced while `blume dev` is running are now printed to the terminal as well as shown in the browser error overlay. On published installs the overlay channel could be unavailable, so an edit that broke frontmatter or content previously produced no message anywhere.
|
|
42
|
+
- 759b148: Fix `blume dev` staying permanently down after a failed structural restart: the route signature is now committed only once the restart succeeds, so the next file change retries the restart instead of taking the hot-reload path against a stopped server.
|
|
43
|
+
- 7cda9bf: The deployment docs claimed every adapter is pulled in automatically; they now say `vercel` and `node` ship with Blume while `@astrojs/netlify` and `@astrojs/cloudflare` must be installed in the project.
|
|
44
|
+
- 559024b: The AI docs now list Codex among the clients the **Connect to MCP** menu offers copy-and-go install for, matching the actual menu, and use American spelling ("labeled") consistently.
|
|
45
|
+
- 7cda9bf: The deployment docs' env-var table understated the Ask AI warning — it fires for every non-gateway provider's default key env var (`OPENROUTER_API_KEY`, `LLMGATEWAY_API_KEY`, `INKEEP_API_KEY`) unless `apiKeyEnv` overrides it — and the sources page's `blume sync --force` comment is now aligned with the lines above it.
|
|
46
|
+
- 559024b: The CLI reference now quotes the actual error `blume build` prints when a `blume dev` server holds the `.blume` runtime — the previous wording was stale and no longer matched the message.
|
|
47
|
+
- 559024b: The configuration overview now names the edit page action by its actual UI label (**Edit on GitHub**) and no longer implies `search` supports only two providers — Algolia and the other providers get a mention.
|
|
48
|
+
- 6d412dc: Add the `Feedback` layout slot to the customization docs' wired-slots table. The slot is real and wired (it replaces the "Was this page helpful?" rating, and `blume add feedback` scaffolds an override for it) but the table — which presents itself as the complete list — omitted it.
|
|
49
|
+
- 7cda9bf: The navigation docs' "built-in icon" link pointed at the Customization page, which says nothing about icons; it now links to the Icon section of the components page.
|
|
50
|
+
- 7cda9bf: The docs landing page's customization sentence read awkwardly ("start replacing … file or even ejecting"); it now reads "start by replacing the built-in components, modifying the single configuration file, or even ejecting".
|
|
51
|
+
- 559024b: The docs homepage's "Why Blume exists" opener now reads "fast, AI-ready, and zero-config", fixing the faulty parallelism in the previous phrasing.
|
|
52
|
+
- 759b148: Documentation fixes:
|
|
53
|
+
|
|
54
|
+
- Restore collapsed `:::warning` / `:::note` callout directives to their multi-line form in the syntax guide, the FAQ, and the Blume agent skill
|
|
55
|
+
- FAQ: soften the oxfmt patch claim to "ships the same fix", include `:::info` in the list of affected container directives, and update the example patch to the shipped `oxfmt@0.58.0` version (which now also preserves titled directives like `:::warning[Heads up]`)
|
|
56
|
+
- AI guide: describe the MCP tool list without a hardcoded count, correct the `agent-readability.json` default-state wording, and drop the reference to the deferred migration skill
|
|
57
|
+
- i18n guide: describe UI translation packs as "over 30 languages" instead of a hardcoded count
|
|
58
|
+
- Quickstart and Deployment: require Node.js 22.12 or newer, matching the package engines
|
|
59
|
+
- Configuration reference: correct the `markdown` feature description (code blocks, heading anchors, image zoom), split the `toc` example into two valid snippets, and document the `github` option (owner, repo, branch, dir)
|
|
60
|
+
- Custom pages: update the `BlumeDataConfig` field list to include `ask`, `codeThemes`, and `toc`
|
|
61
|
+
- Skills guide: use the verified `npx skills add haydenbleasel/blume --skill blume-update-docs` install command
|
|
62
|
+
|
|
63
|
+
- 559024b: The navigation docs' page-actions list no longer mentions the **Ask AI about this page** action removed in 0.6.0, and the edit action is named by its actual UI label, **Edit on GitHub**.
|
|
64
|
+
- 559024b: The SEO docs no longer hardcode a count of configurable features (the list has grown past three) and use American spelling ("honor") consistently.
|
|
65
|
+
- 6d412dc: Fix `blume eject`'s next-steps hint telling bun users to run `bun build` — that invokes Bun's bundler ("error: Missing entrypoints"), not the package.json `build` script, because unlike `dev` the script name is shadowed by a builtin subcommand. The hint now prints `bun run build` (npm already used the `run` form; pnpm/yarn are unaffected).
|
|
66
|
+
- 759b148: `blume eject` now emits the hosted MCP server (endpoint, data snapshot, and `.well-known` discovery documents) and the `/changelog` index page, so ejected apps no longer 404 on routes the generated runtime served.
|
|
67
|
+
- 559024b: `blume eject`'s success message now prints run commands matching your package manager (detected the same way as `blume init`) instead of always suggesting `bun run dev` and `bun run build`.
|
|
68
|
+
- 7cda9bf: `blume eject` discarded the Scalar API reference warnings that `blume dev` and `blume build` print — a spec file that wasn't found (so the ejected page points Scalar at a URL that 404s) or a reference route colliding with a content page went unreported. Eject now surfaces those warnings the same way the generated runtime does.
|
|
69
|
+
- 559024b: `blume eject` now resolves the installed blume package's real location for the `@source` glob in `src/generated/app.css` when it isn't in the project's own `node_modules` (hoisted npm/yarn workspace installs), so Blume's utility classes no longer silently disappear. If resolution fails, the previous default is kept and a warning explains how to adjust the glob.
|
|
70
|
+
- 7cda9bf: `blume eject` rewrote the build script to plain `astro build` without mentioning that the `blume build` post-build artifacts stop being produced — most severely, a `search.provider: "pagefind"` site ejected into a build whose search fails at runtime because the Pagefind index is never created. The eject confirmation and summary now warn exactly which artifacts the project's config actually uses (the Pagefind index with a `pagefind --site dist` post-build hint, hosted search sync, llms.txt/llms-full.txt, sitemap.xml, robots.txt, agent-readability.json, and platform redirect files), and the Eject docs explain how to recreate each one.
|
|
71
|
+
- 759b148: Reword the `BLUME_ENTRY_ID_MISMATCH` suggestion to the configurations that actually resolve it: a single filesystem source, or every filesystem source rooted at `content.root` and partitioned with `include` globs — the previous advice (any root under `content.root`) reproduced the error.
|
|
72
|
+
- 759b148: Fix `.env` parsing corrupting escaped backslashes in double-quoted values (e.g. `"C:\\path\\new"` gained a newline): escape sequences are now expanded in a single pass so each backslash is consumed exactly once.
|
|
73
|
+
- 21aa451: Clicking "Export to EPUB" again while a generation was in flight could leave the menu item permanently reading "Generating…" until reload — the second click captured the in-progress label as the text to restore. The original label is now remembered once, so the button always returns to its proper label.
|
|
74
|
+
- 21aa451: Mixedbread search results are now HTML-escaped before being rendered in the search dialog, so markup in a hit's title or excerpt displays literally instead of being injected into the page. Query matches in those hits also get the same highlight treatment as every other provider.
|
|
75
|
+
- 21aa451: Search result excerpts no longer end with a stray ellipsis when a page has no description and its content is short enough to show in full — previously short content rendered as "some short text…" and empty content as a bare "…".
|
|
76
|
+
- 759b148: Multiple `<Expandable>` (or same-titled accordion) components on one page no longer render duplicate ids; later duplicates get a numeric suffix while the first keeps the plain slug so hash deep-links stay stable.
|
|
77
|
+
- 6d412dc: Fix the FAQ's oxfmt patch instructions for pnpm. The page told Bun and pnpm users alike to add a top-level `patchedDependencies` key to `package.json` — Bun's convention, which pnpm silently ignores, leaving the patch unapplied. The pnpm form (nested under the `pnpm` key, or in `pnpm-workspace.yaml`) is now shown separately.
|
|
78
|
+
- 6d412dc: Restore the "about this page" qualifier in the French `actions.askAI` string ("Demander à l'IA à propos de cette page"). French was the only locale pack that dropped it, making the page-action label identical to the Ask panel's title.
|
|
79
|
+
- 6d412dc: Document three functional frontmatter fields the schema reference omitted: the top-level `hidden` and `noindex` shorthands (for `sidebar.hidden` / `seo.noindex`) and `deprecated`, which renders a "Deprecated" badge in the sidebar. The page claims to list everything a page accepts, and unknown keys are build errors — so working fields users can't discover from the docs are a gap.
|
|
80
|
+
- 7cda9bf: Git-derived "Last updated" dates now follow each filesystem source's own root: with `lastModified: true` and a source configured with a non-default `root` (e.g. `documentation/`), the `git log` pathspec previously pointed at the global `content.root` (`docs/`), so every page silently lost its date.
|
|
81
|
+
- 21aa451: A header logo configured as a public-dir path (e.g. `logo: "/logo.png"`) now renders correctly on sites deployed under `deployment.base` — the light and dark logo images get the base prefix like the favicon and brand link already did, instead of 404ing on every page. Remote http(s) logo URLs pass through unchanged.
|
|
82
|
+
- 21aa451: The Algolia, Typesense, and Orama Cloud search providers now honor the search dialog's language filter on i18n sites. The locale was uploaded with every record at sync time but ignored at query time, so results always mixed every language regardless of the per-language toggle.
|
|
83
|
+
- 759b148: Pressing Enter to confirm an IME conversion (CJK input) no longer submits the Ask AI question or activates the selected search result mid-composition.
|
|
84
|
+
- 21aa451: `blume init --eject` now rewrites the scaffolded package.json scripts to run Astro directly after a successful eject (matching `blume eject`), and its next-steps output includes the `cd <dir>` hint and package-manager-appropriate commands. When eject can't run yet because dependencies aren't installed, the fallback explains that and points at `npx blume eject --yes` (or the pnpm/yarn/bun equivalent) instead of a bare `blume eject` that isn't on PATH.
|
|
85
|
+
- 559024b: Inline code with an unknown highlight language (for example a typo'd `` `foo(){:typescrpt}` ``) now strips the `{:lang}` marker and renders as plain inline code instead of shipping the literal marker in the page.
|
|
86
|
+
- 639c802: The Search input and Ask AI textarea now render at 16px on touch devices (`pointer-coarse:text-base`), so iOS Safari no longer auto-zooms the page when they receive focus; fine-pointer devices keep the 14px size.
|
|
87
|
+
- 7cda9bf: `blume build --isolated` now honours `--analyze`, `--budget-js`, and `--budget-css`, measuring the isolated build's own output. Previously the isolated path skipped the bundle report and budget gate entirely, so a CI run like `blume build --isolated --budget-js 100` exited 0 without measuring anything — a silent false pass.
|
|
88
|
+
- 21aa451: Broken-link and broken-anchor diagnostics now point at the correct line of the source file. Line numbers were counted on the frontmatter-stripped body, so a link below a frontmatter block was reported several lines above where it actually sits (e.g. line 2 instead of line 6 after a 4-line block).
|
|
89
|
+
- 559024b: llms.txt, llms-full.txt, and agent-readability.json now layer `deployment.base` onto their root-relative URLs when no `site` is configured, so advertised links like `/llms.txt` and page routes resolve under a subpath deployment instead of 404ing.
|
|
90
|
+
- 759b148: Exclude hidden and `noindex` pages from `llms.txt`/`llms-full.txt` (matching the sitemap) and percent-encode the emitted page URLs.
|
|
91
|
+
- 21aa451: The announcement banner's dismiss button had a hardcoded English "Dismiss announcement" accessibility label. It now resolves through the UI strings dictionary (`banner.dismiss`), ships translations in every built-in locale pack, and can be overridden per locale via `i18n.ui`.
|
|
92
|
+
- 759b148: Previously hardcoded UI chrome strings (search dialog groups/hints/error, export menu, navigation and theme-toggle aria-labels, nav-tree back/deprecated labels, changelog reveal button, Mermaid error, Ask AI transcript prefixes) now come from the i18n dictionary with English fallback.
|
|
93
|
+
- 7cda9bf: Localize header-tab dropdown item paths under i18n: a tab's own path was locale-prefixed (`/docs` -> `/fr/docs`) but its `items[].path` entries were not, so dropdown links always pointed at the default locale. External item URLs still pass through untouched, and selector items keep their intentionally locale-specific targets.
|
|
94
|
+
- 559024b: The `<Math>` component is now wired into the generated runtime whenever math can actually appear: block math (`$$…$$`) in plain `.md` files, math in staged remote-source content, and explicitly authored `<Math code="…" />` tags all count. Detection previously only scanned local `.mdx` files for a literal `$$`, so those cases rendered a raw "Expected component Math to be defined" MDX error instead of the equation.
|
|
95
|
+
- 21aa451: The MCP `search_docs` fallback excerpt (used when a page has no description) now appends an ellipsis only when the content was actually truncated. Short pages no longer get a fake truncation marker, an empty page no longer yields a bare "…", and a cut that lands on whitespace is trimmed before the marker.
|
|
96
|
+
- 7cda9bf: Normalize `mcp.route` to a leading slash (and no trailing slash) like other configured routes: a slash-less value such as `"docs-mcp"` was string-concatenated onto the site origin, so `/.well-known/mcp.json`, the MCP server card, and `agent-readability.json` advertised a malformed URL like `https://acme.comdocs-mcp`.
|
|
97
|
+
- 759b148: MCP URLs now carry `deployment.base`: the server URL advertised by `/.well-known/mcp.json` and the server card, and the page URLs returned by the `search_docs` and `list_pages` tools, previously pointed at base-less paths on subdirectory deployments.
|
|
98
|
+
- 759b148: An mdx-remote source missing both `{ github }` and `{ url, files }` now always fails with `BLUME_SOURCE_MISCONFIGURED`: the config is validated before the cached-fetch path, which previously masked it as `BLUME_SOURCE_FETCH_FAILED` or silently served stale cached entries with an offline warning.
|
|
99
|
+
- 559024b: `blume build` with the Netlify adapter now surfaces only the `.netlify/v1` deploy bundle instead of replacing the whole `.netlify` directory, so the `.netlify/state.json` written by `netlify link` survives every build.
|
|
100
|
+
- 7cda9bf: Server builds targeting Netlify or Cloudflare now warn up front when `@astrojs/netlify` or `@astrojs/cloudflare` isn't installed, naming the exact package to add. Previously the generated `astro.config.mjs` imported the adapter unconditionally — including when it was auto-selected from platform env vars — so the build died with an opaque `ERR_MODULE_NOT_FOUND` from a hidden generated file. Both adapters are now declared as optional peer dependencies so package managers surface and satisfy the requirement.
|
|
101
|
+
- 6d412dc: Fix Node server builds (`output: "server"`, `adapter: "node"`) publishing every deploy artifact to a directory the server never serves. Astro puts served static files in `dist/client/` and `@astrojs/node`'s standalone server reads only that directory, but Blume wrote `sitemap.xml`, `robots.txt`, `llms.txt`/`llms-full.txt`, `agent-readability.json`, redirect files, and the Pagefind bundle into `dist/` — logging success while every one of those URLs 404'd in production. The same wrong directory also fed `--analyze` and the `--budget-js`/`--budget-css` gate, which read the nonexistent `dist/_astro`, reported "No client JavaScript emitted", and passed every budget against 0 bytes. Both the deploy static dir and the isolated-build static dir now point at `dist/client/` for Node server builds; Netlify (publishes `dist/`), Cloudflare (serves the `outDir` root), and Vercel (`.vercel/output/static`, already special-cased) are unchanged.
|
|
102
|
+
- 759b148: The generated 404 page's "home" link now routes through `withBase` instead of a hardcoded `/`, so it lands on the site root under `deployment.base`.
|
|
103
|
+
- 759b148: The Notion source's `publishedValue` now defaults to `Published` as documented: pages whose Status/select property holds any other value import as drafts, while pages without a Status property stay published.
|
|
104
|
+
- 759b148: Treat numeric-prefixed index files (`01-index.mdx`) as directory indexes everywhere routing already does: they now sort first in the sidebar, keep their group's route path intact, and resolve relative links against their own route.
|
|
105
|
+
- 559024b: An OpenAPI spec file that isn't a valid document (an empty file, or YAML that parses to a scalar or list) now fails with a clear "is not a valid OpenAPI document" error and a fix-the-file suggestion, instead of crashing with a raw TypeError and a misleading reachability hint.
|
|
106
|
+
- 559024b: Two Blume-rendered OpenAPI sources that resolve to the same route now emit a warning ("keeping the first"), matching the Scalar renderer, instead of silently dropping the second spec's pages.
|
|
107
|
+
- 559024b: An OpenAPI spec that parses but declares no operations (say, a config file pointed at by mistake) now emits a build warning naming the spec, instead of silently shipping an empty API reference tab.
|
|
108
|
+
- 21aa451: Operation-level parameters now override path-level parameters with the same name and location, per the OpenAPI spec, so a re-declared parameter renders once in the parameters table instead of twice — and no longer duplicates itself in sample request URLs (`?limit=0&limit=0`).
|
|
109
|
+
- 21aa451: `blume build --output server` now participates in platform adapter auto-detection. On Vercel, Netlify, or Cloudflare Pages, the matching adapter is selected just as if `deployment: { output: "server" }` had been set in blume.config.ts — previously the flag produced a server build with no adapter and the Astro build failed.
|
|
110
|
+
- 6d412dc: Render the yarn tab of a `package-install` `ci` command as `yarn install --immutable`. It previously emitted `--frozen-lockfile`, which Yarn 4 removed — so there was no yarn version where both the generated `ci` command and the Berry-only `yarn dlx` (from `exec`) worked; a Yarn 4 reader copying the tab got "Unsupported option name --frozen-lockfile".
|
|
111
|
+
- 759b148: Page actions now reach the raw-markdown endpoint under `deployment.base`: the "Open in ChatGPT/Claude/…" links and "Copy as Markdown" previously fetched the base-less `/page.md` path (a 404) on subdirectory deployments.
|
|
112
|
+
- 759b148: The search dialog's ⌘J preview hint and the Ask AI panel's ⌘I hint now show "Ctrl" on non-Apple platforms, matching the existing ⌘K/Ctrl K button hint.
|
|
113
|
+
- 759b148: Include CHANGELOG.md in the published package so it's browsable on npm and unpkg.
|
|
114
|
+
- 559024b: The README's CONTRIBUTING link now uses an absolute GitHub URL so it no longer 404s on the npm package page, and the opening tagline no longer repeats the "drop Markdown into a folder" pitch that the very next paragraph makes in full.
|
|
115
|
+
- 7cda9bf: The README dropped a verb in "run `blume eject` to a standalone Astro app"; it now reads "run `blume eject` to get a standalone Astro app".
|
|
116
|
+
- 6d412dc: Update the README's API-reference bullet to lead with the native renderer. Since the 0.5.0 rebuild the default is Blume's own reference (one real page per operation, woven into sidebar/search/`llms.txt`); Scalar is the opt-in embed (and the AsyncAPI path) with the "Try it" playground. The bullet still described the pre-0.5.0 Scalar-only behavior.
|
|
117
|
+
- 759b148: Remove the dead `itemsRoot` registry export, which pointed at a directory that doesn't exist.
|
|
118
|
+
- 759b148: Remove the unused `deepmerge` dependency.
|
|
119
|
+
- 21aa451: `$ref`s to `components.requestBodies` and `components.responses` are now resolved on operation pages, so a referenced request body renders its real content type, schema, and code-sample bodies (instead of an empty `application/json` section and samples with no body), and a referenced response shows its description and schema.
|
|
120
|
+
- 6d412dc: Fix a `path: "/"` navigation tab falsely triggering tab-section scoping under `basePath` or a non-default locale. The root-tab exclusion compared the literal `"/"` after tab paths had already been localized and rebased, so with `basePath: "/docs"` (or on a `/fr` locale tree) the root tab's final path matched a root-level `(group)` folder's route path and hoisted that group's pages above its subgroups — the sidebar ordered differently with a base than without one under `display: "group"`/`"page"`. The exclusion now compares against the tree's based, localized root.
|
|
121
|
+
- 7cda9bf: A section filter picked in the search dialog persisted after the query changed, even when the new results no longer included that section — and since the filter pills hide when fewer than two sections match, the stale filter could empty the results with no visible way to clear it. The filter now resets automatically when its section is missing from the new result pool, and the search re-runs unfiltered.
|
|
122
|
+
- 21aa451: A search client that fails to load in production (for example a transient failure fetching the Pagefind bundle) now shows the "Something went wrong" error message in the search dialog instead of the misleading "Search is available in the production build" dev-only hint. Loading still retries the next time the dialog opens.
|
|
123
|
+
- 21aa451: Search indexes now honor `<Visibility>` audiences. Content marked `for="agents"` no longer appears in the site's search dialog excerpts or gets uploaded to hosted search providers (Algolia, Orama Cloud, Typesense, Mixedbread), and the MCP `search_docs` index and Ask AI grounding now apply the same rules as `get_page` and llms-full.txt: web-only content is removed and agents-only content is included.
|
|
124
|
+
- 6d412dc: Stop the search dialog showing "Search is available in the production build." on production sites while the search client is still loading. Typing before the lazy client import and index fetch resolved (seconds, on a slow connection) rendered the dev-only hint for every keystroke because the not-loaded and dev-missing states were indistinguishable. The load window now shows a neutral placeholder and re-renders with real results (or the error state) once the load settles.
|
|
125
|
+
- 759b148: A search provider request that fails (network error, provider outage) now shows an error message in the search dialog instead of silently leaving a blank results pane.
|
|
126
|
+
- 6d412dc: Index a config-sidebar section's landing page under its own section facet. A section declared as `sidebar: [{ label: "Guides", root: "guides/index", items: […] }]` carries its landing route on the group node, which the search crumb index skipped — so `/guides` itself indexed under the "Docs" default with an empty breadcrumb, the search dialog's "Guides" filter pill omitted the section's own landing page, and hosted-provider syncs uploaded the wrong facet for it. (Filesystem sidebars were unaffected: their index pages are page leaves, which still win over the group entry when both exist.)
|
|
127
|
+
- 7cda9bf: Recognize setext headings (`Title` underlined with `=` or `-`) and ATX headings indented 1-3 spaces when extracting headings, matching what the renderer actually renders — these previously vanished from the TOC, search, and page metadata and triggered false `BLUME_BROKEN_ANCHOR` warnings. Underline look-alikes (front matter delimiters, thematic breaks, list/blockquote closers, table delimiter rows, fenced-code content) are not misread as setext underlines.
|
|
128
|
+
- 759b148: Ship the README and LICENSE in the npm tarball so the package page on npm shows the project readme and license.
|
|
129
|
+
- 21aa451: `sitemap.xml` now includes custom `.astro` pages and the generated `/changelog` index. A site with a custom `pages/index.astro` landing page previously published a sitemap missing its own root URL, and the indexable changelog page was absent too. Dynamic (`[param]`) and private (`_partial`, `.well-known`) routes stay excluded, and the deployment base is layered onto the new URLs like every other entry.
|
|
130
|
+
- 559024b: sitemap.xml no longer lists user-authored error pages: a custom `pages/404.astro`/`pages/500.astro` (or a `404` content override) is excluded, since error routes aren't crawlable destinations.
|
|
131
|
+
- 6d412dc: Fix the build summary's sitemap line telling users to "set deployment.site" when the sitemap was deliberately disabled. The line now distinguishes `seo.sitemap: false` from a missing `deployment.site`, so the remediation hint only appears when it's the actual fix.
|
|
132
|
+
- 559024b: The bundled Blume agent skill now states the correct minimum Node.js version (22.12, matching the package's `engines` field) and clarifies that the MCP server is an endpoint served by your docs site itself, not a Blume-operated hosted service.
|
|
133
|
+
- 7cda9bf: The update-docs skill claimed `blume build` validates links and anchors; it now runs `blume validate` for link and anchor checks, with build covering frontmatter and duplicate routes.
|
|
134
|
+
- 21aa451: Remote CMS images are now content-addressed by their query-less URL. Notion's pre-signed file URLs change their query string on every API call, so the same image was written to a new file on each refresh — triggering a full-reload loop on every dev poll tick and piling up duplicate files under `blume-assets/`. Repeated builds now reuse one stable filename per asset.
|
|
135
|
+
- 759b148: `<Steps titleSize>` now actually resizes step titles: `<Step>` consumes the title-size variables `<Steps>` sets, with fallbacks that keep the default rendering unchanged.
|
|
136
|
+
- 759b148: `<Tabs>` triggers and panels now get stable generated ids and are wired both ways with `aria-controls`/`aria-labelledby`, so screen readers announce which panel each tab controls without requiring an explicit `id` prop.
|
|
137
|
+
- 759b148: Recognize `~~~` tilde code fences when extracting headings, links, and component tags, fixing false `BLUME_BROKEN_LINK`/`BLUME_UNKNOWN_COMPONENT` diagnostics and phantom heading anchors for tilde-fenced content (a ```line inside a`~~~` fence no longer toggles the fence state either).
|
|
138
|
+
- 21aa451: Fix two doc callouts whose body text was silently dropped at render. The `:::warning` examples on the syntax page (including the fenced sample that teaches the form) and the oxfmt FAQ had their body collapsed onto the directive fence line — the exact formatter collapse the FAQ itself documents — so the directive parser kept only the label and rendered an empty callout. The body now sits on its own line after `:::warning[Title]`, so both callouts render their text again.
|
|
139
|
+
- 759b148: `useAskAI().ask()` now catches a thrown fetch (offline, DNS failure, CORS) and shows the error notice instead of rejecting and leaving an empty assistant message stuck as a placeholder.
|
|
140
|
+
- 559024b: `useSearch()` now guards against out-of-order provider responses: only the latest query may commit results or clear `loading`, so a slow response for "a" no longer clobbers the results for "ab". `loading` also flips on before the lazy client creation, so the first search's index download shows as loading instead of idle.
|
|
141
|
+
- 6d412dc: Stop `blume validate` flagging links to fallback-rendered locale routes as broken. With i18n fallback active, an untranslated page is prerendered at its localized URL (`/fr/guide` serving the fallback content) — the i18n docs promise "the link works" — but the validator only accepted routes backed by a real page, so a French page linking an untranslated sibling failed CI with `BLUME_BROKEN_LINK`. The validate command now derives the fallback-materialized routes from the route manifest and accepts them as link targets.
|
|
142
|
+
- 21aa451: `blume validate` no longer reports links to custom `.astro` pages or the generated `/changelog` index as broken. A docs page linking to a custom landing page (e.g. `[home](/)` with a `pages/index.astro`) previously failed validation — and CI — with BLUME_BROKEN_LINK; those routes now count as known link targets. Anchors on them are accepted unchecked, since their headings aren't indexed.
|
|
143
|
+
- 6d412dc: Fix `blume validate` resolving relative links from localized index pages one directory too high. Index detection only matched a literal `index.md(x)` basename, so a dot-parser localized index (`guides/index.fr.mdx`, route `/fr/guides`) and a shared locale-agnostic one (`guides/index.$.mdx`) weren't recognized as directory indexes — `./setup` resolved to `/fr/setup` instead of `/fr/guides/setup` and a fully correct site failed validation with `BLUME_BROKEN_LINK`. Index-ness is now derived from the locale-stripped `navPath`, matching how route mapping recognizes these files.
|
|
144
|
+
- 759b148: `blume validate --strict` no longer fails on info-level notes (like `BLUME_ASSETS_UNCHECKED` when there is no `public/` directory) — it treats warnings and errors as failures, as documented.
|
|
145
|
+
- 759b148: Preserve exact redirect status codes in the generated `vercel.json` (using `statusCode` instead of the boolean `permanent`), so a configured 301 no longer ships as 308 and a 302 no longer ships as 307 on Vercel.
|
|
146
|
+
- 21aa451: `<Visibility>` is now honored in agent-facing Markdown. Content marked `for="web"` used to leak into llms-full.txt, the `.md`/`.mdx` mirrors, and the MCP `get_page` tool, and `for="agents"` content appeared wrapped in literal `<Visibility>` tags; web-only blocks are now removed from those outputs and agents-only blocks are unwrapped. Fenced code samples that show `<Visibility>` markup are left untouched.
|
|
147
|
+
- 21aa451: A `paths` entry that is a `$ref` to a shared path item now emits a warning naming the path and the spec, instead of silently dropping its operations from the API reference.
|
|
148
|
+
- 559024b: Hydrated component-override wrapper filenames are now injective: distinct override keys that only differ in punctuation (for example `"Foo.Bar"` and `"Foo_Bar"`) no longer collapse to the same generated `.astro` file, which raced two concurrent writes at one path and silently rendered one key with the other's component.
|
|
149
|
+
|
|
150
|
+
## 0.7.0
|
|
151
|
+
|
|
152
|
+
### Minor Changes
|
|
153
|
+
|
|
154
|
+
- 7799732: Remove the migration tooling and the Mintlify-compatibility surface. This is a breaking change for projects upgrading from 0.5.x/0.6.x.
|
|
155
|
+
|
|
156
|
+
**Migration tooling is gone for now.** `blume migrate <tool>`, the automatic `docs.json` bridge mode, and the `mintlify` content source are removed; a migration path will return in a future release.
|
|
157
|
+
|
|
158
|
+
**Icons are Lucide-only.** The FontAwesome and Tabler icon sets, the `icons.library` config, the `iconType` frontmatter/prop, and the `fa6-*`/`tabler` name prefixes are removed. Use bare Lucide names everywhere an icon is accepted.
|
|
159
|
+
|
|
160
|
+
**Removed config fields** (validate-but-never-rendered Mintlify-compat): `banner.color`, `banner.type`, top-level `favicon` (favicons are detected by filename — drop `icon`/`favicon.{svg,png,ico}` in the project root or `public/`), `navigation.chromeVariants`, `icons`, `seo.metatags`, `search.prompt`, `variables`, `theme.backgroundDecoration`, and `content.assets` (move root asset dirs into `public/` — Astro serves it at the site root).
|
|
161
|
+
|
|
162
|
+
**Removed frontmatter keys** (unknown keys are build errors): `sidebarTitle` (use `sidebar.label`), `tag` (use `sidebar.badge`), `mode`, `public`, `rss`, `hideApiMarker`, `hideFooterPagination`, `groups`, `keywords`, and `iconType`.
|
|
163
|
+
|
|
164
|
+
**Removed components:** `<Warning>` (use the `:::warning` directive) and the `<ParamField>`/`<ResponseField>`/`<RequestField>`/`<ApiField>` field family (use `<TypeTable>`, or the OpenAPI reference for spec'd APIs).
|
|
165
|
+
|
|
166
|
+
- 331c6cb: Isolate `<Component />` previews from the docs CSS and let projects style them with their own design tokens. Previews used to render inline in the page, where the theme's prose styles (margins, typography, link/heading rules pierce `not-prose` by design) bled into the example — so a shadcn button previewed with docs styling on top. Each example now renders in its own generated route (`{basePath}/blume-examples/<path>`) embedded as an iframe: the frame boundary keeps every docs style out, and the frame loads a dedicated Tailwind entry with just preflight, utilities scanned from the example files and their imports, and Blume's design tokens (so `bg-background`-style classes still follow the site palette). The frame mirrors the site's light/dark toggle live, setting both `data-theme` and a `.dark` class so either dark-mode convention works. To bring your own tokens — e.g. shadcn variables or `@theme` mappings — point the new `examples.css` config at a stylesheet; it's injected into every frame after Blume's defaults. The existing string form stays as shorthand for `examples.source`: `examples: { source: "examples", css: "examples/theme.css" }`.
|
|
167
|
+
- 24f63c2: Enable the React Compiler automatically whenever React is used. Islands and other React components are now auto-memoized by `babel-plugin-react-compiler` (which ships with Blume — nothing to install), so hand-written `useMemo`/`useCallback` is no longer needed. Opt out with `react: { compiler: false }` in `blume.config.ts`.
|
|
168
|
+
|
|
169
|
+
### Patch Changes
|
|
170
|
+
|
|
171
|
+
- e816f99: Apply the `markdown.codeBlocks.theme` config to code rendering. The `theme.{light,dark}` Shiki theme names (defaults `github-light`/`github-dark`) were validated but never read; they now drive every highlighted surface — fenced code blocks, inline `` `code`{:lang} `` snippets, the `<CodeBlock>` and `<Component>` source panes, OpenAPI request/response samples, and `<Diff>` — so e.g. `markdown: { codeBlocks: { theme: { dark: "vesper" } } }` recolors dark-mode code while an unset side keeps its github default. Any bundled Shiki theme name works.
|
|
172
|
+
- fad14bc: Fix `deployment.base` so a subdirectory deploy (e.g. GitHub Pages project sites) prefixes everything it renders, not just bundled assets. Previously Astro prefixed `_astro/*`/fonts/CSS but Blume's own output stayed base-less, so navigation links, in-content Markdown links, canonical URLs, Open Graph images, the sitemap, `llms.txt`, RSS feeds, JSON-LD, `agent-readability.json`, the robots `Sitemap:` line, and search-result links all pointed at the wrong (base-less) path. Each is now prefixed with the deployment base at the point it's emitted — via `import.meta.env.BASE_URL` in components and templates, and `deployment.base` in the build-time SEO files — while active-route matching stays in base-less logical space. Composes with the new site-wide `basePath`: with both set, a link resolves to `{deployment.base}/{basePath}/page`.
|
|
173
|
+
- 75cd991: Fix `blume dev` serving stale 404s after a content file or folder is renamed, added, or removed. Two dev-only Astro/Vite issues combined to leave a page 404ing (`Entry docs → … was not found`) until a manual restart: Astro's in-memory content store only refreshes on a cold container restart — its in-place restart does an incremental sync and its glob watcher misses directory renames — and a full reload could fail to resolve the `astro:server-app` dev entry (`Failed to load url astro:server-app.js`), corrupting the SSR module runner. Now a route-set change (add/remove/rename, including folders) triggers a clean dev-server restart that re-globs the content store, and a Vite resolver shim (`serverAppResolvePlugin`) keeps full reloads from breaking. Editing a page body still hot-reloads without a restart.
|
|
174
|
+
- 21d4473: Fix blank UI chrome (empty search labels, aria-labels, skip link) on `ui`-less `PageLayout`/`RootLayout` pages when the consuming project resolves Zod 4. The English baseline was derived with `uiStringsObject.parse({})`, relying on each group's nested `.default({})` to deep-populate its inner field defaults — Zod 3 behavior. Zod 4's `.default()` returns the literal default without re-parsing it through the inner type, so every group collapsed to `{}` and a `ui`-less layout rendered empty strings. Derive the baseline by naming each group explicitly so field defaults apply on both Zod 3 and 4, and merge component dictionaries (`Search`, `PageFeedback`) over the baseline per key so a partial or empty strings object still falls back to defaults.
|
|
175
|
+
- fa18a6c: Add a top-level `basePath` config option — a site-wide mount point that prepends a segment to every generated route (e.g. `/docs/getting-started`) while staying invisible to the sidebar/nav tree, so no wrapper group appears. Links (write them as if mounted at root), redirects, the sitemap, canonical URLs, Open Graph image URLs, `llms.txt`/`llms-full.txt`, and the search index all flow through it; public assets stay at the site root. It's distinct from a per-source `prefix` (which namespaces one source and adds a group) and from `deployment.base` (Astro's host-subdirectory base) — the two compose, so with both set a page lands at `{deployment.base}/{basePath}/page`.
|
|
176
|
+
- b6d0761: Fix `blume dev`/`build` crashing on Windows with "The URL must be of scheme file" while generating the content config. The generated `content.config.ts` embedded each collection's glob `base` as a raw absolute path, and Astro's glob loader resolves it with `new URL(base, config.root)` — on Windows the drive letter (`C:\…`) is parsed as a URL scheme, so the result isn't a `file:` URL and Astro's subsequent `fileURLToPath` throws. Absolute bases are now emitted as `file://` URLs (via `pathToFileURL`) so the drive letter can't be mistaken for a scheme; relative bases (e.g. an ejected `blume-staged`) pass through unchanged.
|
|
177
|
+
|
|
178
|
+
## 0.6.7
|
|
179
|
+
|
|
180
|
+
### Patch Changes
|
|
181
|
+
|
|
182
|
+
- 37e1434: Make changelog entry heading/paragraph spacing actually apply. The `h2`/`h3`/`p` margins were normal-weight utilities, which Tailwind Typography's `.not-prose` margin reset outranked, so subsequent section headings still butted against the paragraph above. Mark the margins `!important` so they win.
|
|
183
|
+
- aa0665c: Stop the inline-code pill background from leaking into `not-prose` components. The hand-written `.prose :not(pre) > code` rule lacked the `not-prose` exclusion that Tailwind's generated prose rules carry, so components like the `<TypeTable>`, OpenAPI parameter/schema tables, and operation paths inherited a gray pill — which, as a grid cell, stretched to fill its column and painted edge-to-edge. Scope the rule to skip `not-prose` subtrees so those components render their own intended code styling.
|
|
184
|
+
|
|
185
|
+
## 0.6.6
|
|
186
|
+
|
|
187
|
+
### Patch Changes
|
|
188
|
+
|
|
189
|
+
- aae9653: Give changelog entry content proper vertical rhythm. Section headings (`h2`/`h3`) now carry a top margin so a subsequent heading reads as a new section rather than butting against the paragraph above it, and paragraphs gain spacing between them. The entry's first and last elements keep flush outer margins.
|
|
190
|
+
- a77a968: Hoist loose pages above groups inside tab-owned sidebar sections. When a content source uses a `prefix` (so its pages nest under a group that a tab surfaces as the sidebar), the section's top-level pages now sort above its groups — matching the tree-root behavior — instead of interleaving alphabetically.
|
|
191
|
+
|
|
192
|
+
## 0.6.5
|
|
193
|
+
|
|
194
|
+
### Patch Changes
|
|
195
|
+
|
|
196
|
+
- 3f3402d: Collapse `display: group` sidebar sections by default. Groups now start closed and open only along the active path — the current page's ancestor groups stay expanded, so just the section you're in is open. Top-level groups no longer force open; use `collapsed: false` in folder meta to pin a group open.
|
|
197
|
+
- beb5206: Hoist root-level pages above groups in every sidebar display mode. Previously only `flat` pulled loose top-level pages to the top; now `group` and `page` modes do too, so a root page never reads as a group's trailing child. Deep per-level hoisting remains exclusive to `flat`.
|
|
198
|
+
|
|
199
|
+
## 0.6.4
|
|
200
|
+
|
|
201
|
+
### Patch Changes
|
|
202
|
+
|
|
203
|
+
- 7b70ddd: Order changelog entries newest-first in the sidebar. Pages with `type: changelog` now sort by publish date descending — matching the generated `/changelog` timeline — instead of alphabetically by version label, so a changelog section reads latest-at-the-top. Explicit `sidebar.order` still wins.
|
|
204
|
+
- 4a7aa42: Emit `llms.txt` by default. `ai.llmsTxt` now defaults to `true`, so machine-readable docs ship out of the box alongside the already-on `agentReadability` and `contentSignals` signals — set `ai: { llmsTxt: false }` to opt out.
|
|
205
|
+
- 8252012: Remove the unused `theme.strict` config field. It validated but nothing ever read it, so it was a no-op; dropping it keeps the config surface honest. Any leftover `theme: { strict: … }` is now rejected as an unknown key.
|
|
206
|
+
|
|
207
|
+
## 0.6.3
|
|
208
|
+
|
|
209
|
+
### Patch Changes
|
|
210
|
+
|
|
211
|
+
- 1421891: Fix the mobile menu on changelog (and other "bare") pages: the header hamburger only locked page scroll because bare layouts skipped the drawer entirely. The drawer now renders on mobile — with the section tabs kept visible when the page tree is empty — while desktop keeps the bare landing layout.
|
|
212
|
+
- 78ad357: Render the OG card header as the logo only — no brand-name label beside it — so a wordmark logo no longer reads "Ultracite Ultracite". Without a logo, the accent tile with the brand initial still stands in.
|
|
213
|
+
- a155af5: Hide the "Previous"/"Next" eyebrow labels on pagination cards below `md`, so the stacked mobile cards show just the page title and arrow instead of a stubby two-line pill.
|
|
214
|
+
|
|
215
|
+
## 0.6.2
|
|
216
|
+
|
|
217
|
+
### Patch Changes
|
|
218
|
+
|
|
219
|
+
- 7b84669: Match active header tabs and nav-selector items on path boundaries, so a `/api` tab is no longer highlighted on `/api-reference/*` routes.
|
|
220
|
+
- 7ed2b2b: Decode Ask AI streams with `{ stream: true }` (in both the built-in panel and `useAskAI`), so multi-byte characters split across network chunks no longer render as `�`.
|
|
221
|
+
- 6f44994: Stop downloading and rewriting image URLs that appear inside fenced code blocks when materializing remote (e.g. Notion) assets — code samples keep showing what the author wrote.
|
|
222
|
+
- dfa956e: Acquire the dev lock atomically (`wx` create) so two `blume dev` processes started simultaneously can no longer both claim `.blume/` and corrupt each other's runtime.
|
|
223
|
+
- 6f44994: Keep a trailing `#` that is part of a heading's text (`## What is C#`) in derived titles, search entries, and the manifest TOC — only a whitespace-preceded closing hash sequence is stripped, per CommonMark.
|
|
224
|
+
- 9d60b00: Remove `markdown.math` and `markdown.code.inline` from the `BlumeConfig` authoring type — both features are always-on and the strict config schema rejects the keys, so configs written from autocomplete failed to load.
|
|
225
|
+
- 5468295: Fix code-fence meta parsing: `subtitle="..."` no longer reads as the block title, and the word "lineNumbers" inside a quoted title no longer switches on the line-number gutter.
|
|
226
|
+
- 9d60b00: Make `content.defaultType` actually apply: the frontmatter schema no longer forces `type: "doc"` onto every untyped page.
|
|
227
|
+
- 7ed2b2b: Copy buttons on Twoslash-annotated code blocks now copy the source only, stripping the hover popups' type signatures and docs that are nested inside the code element.
|
|
228
|
+
- dfa956e: Re-bake the dev runtime's `site` fallback when Vite bumps to a free port, so OG images, canonicals, and other site-gated URLs point at the port actually serving instead of the one that was busy.
|
|
229
|
+
- dfa956e: `blume doctor` now checks Node against the package's declared `engines` minimum (>=22.12.0) instead of a stale hardcoded 20, so unsupported Node versions are actually flagged.
|
|
230
|
+
- 36ff4da: Recognize a default-locale filename suffix under the `dot` i18n parser: `intro.en.mdx` now pairs with `intro.fr.mdx` on the `/intro` translation key instead of routing to a literal `/intro.en`.
|
|
231
|
+
- dfa956e: Strip unquoted inline `# comments` from `.env` values, matching dotenv/Vite — a line like `GITHUB_TOKEN=abc # note` no longer hands sources a token with the comment appended.
|
|
232
|
+
- 7e0f413: Make example wrapper filenames injective: distinct example paths like `button.demo` and `button-demo` no longer collide onto one generated wrapper (which made one example render the other's component).
|
|
233
|
+
- 4ed9f6a: Align `hasIcon` with `resolveIcon` for unknown prefixes: `tabler:check` no longer passes the existence check while rendering nothing, and unknown-prefix icons now trigger the nav "unknown icon" diagnostic.
|
|
234
|
+
- 7e0f413: Decode percent-encoded request paths in markdown content negotiation, so `Accept: text/markdown` requests for non-ASCII routes serve the `.md` variant instead of silently falling through to HTML.
|
|
235
|
+
- 7e0f413: Check custom `.astro` pages (not just content pages) before generating the MCP endpoint and the `/changelog` index, so a user page at those routes warns and wins instead of silently colliding.
|
|
236
|
+
- 6f44994: Import nested Notion blocks: children of list items (and other leaf blocks) were silently dropped; nested bullets now render indented under their parent item.
|
|
237
|
+
- 4ed9f6a: Take the OG card's brand initial by code point, so a site title starting with an emoji no longer renders a blank accent tile (a split surrogate pair).
|
|
238
|
+
- d660cf6: Stop entity-escaping backtick code in OpenAPI descriptions: inline code and fences like `/pets/{petId}` now render verbatim instead of showing `{` entities, while surrounding prose is still MDX-neutralized.
|
|
239
|
+
- d660cf6: Cap remote-spec retry backoff at 10s: a server answering 429/503 with a large `Retry-After` no longer stalls `blume build` for hours.
|
|
240
|
+
- d660cf6: Mount a root-routed OpenAPI reference (`route: "/"`) without emitting `//tag/operation` double-slash routes or a malformed `/index.mdx` overview ref.
|
|
241
|
+
- d660cf6: Disambiguate OpenAPI reference slugs when distinct routes slugify identically (`/api/v1` vs `/api-v1`), so one spec no longer silently overwrites the other's data in the `blume:openapi` module.
|
|
242
|
+
- d660cf6: Render one OpenAPI overview section per tag slug: declared tags that slugify identically (`Store` and `store`) no longer list every shared operation twice.
|
|
243
|
+
- 5468295: Map `yarn global add`/`yarn global remove` in `package-install` fences onto each manager's global form instead of rendering nonsense `npm run global add …` tabs.
|
|
244
|
+
- 36ff4da: Percent-decode link paths and fragments before validation, so browser-copied links to non-ASCII routes and anchors (`/caf%C3%A9`, `#caf%C3%A9`) are no longer reported broken.
|
|
245
|
+
- 6f44994: Make `pollInterval` hot-reload actually observe remote changes: the poller now fetches fresh instead of re-reading the dev snapshot cache, and seeds its baseline from what the dev server served so the first remote change is never swallowed. Applies to the GitHub-releases, Notion, Sanity, and remote-MDX sources.
|
|
246
|
+
- b8a1b24: Fix folder `meta.ts` being ignored and doc pages 404ing in dev when a `content.sources` filesystem source's `root`/`prefix` diverges from `content.root`. Folder meta is now discovered per filesystem source — scanned under each source's own root and keyed by its route prefix — so a `meta.ts` inside a prefixed source (e.g. `{ type: "filesystem", root: "docs", prefix: "docs" }`) lines up with its prefixed sidebar group path and its `title`/`order` apply. A project with a single filesystem source now roots the generated `docs` collection at that source's own `root`, so entry ids resolve in dev (not just in static builds). A residual mismatch that can't be reconciled — a second filesystem source rooted outside the collection base — now raises a build-time error (`BLUME_ENTRY_ID_MISMATCH`) instead of silently 404ing at runtime.
|
|
247
|
+
- 7b84669: Apply locale-specific folder meta for prefixed filesystem sources under dir-parser i18n: `docs/fr/guides/meta.ts` now keys to `fr/docs/guides`, matching the navigation lookup, instead of being silently ignored.
|
|
248
|
+
- 7ed2b2b: Hide the mobile hamburger on the Scalar reference layout: it has no drawer to open, so tapping it only locked page scroll.
|
|
249
|
+
- 6f44994: Compile `**/` in remote-MDX include patterns to whole path segments, matching tinyglobby semantics — `docs/**/guide.md` no longer matches `docs/subguide.md`.
|
|
250
|
+
- 7e0f413: URI-encode RSS item links and guids (matching the sitemap), so routes with spaces or non-ASCII characters emit valid feed URLs.
|
|
251
|
+
- 7ed2b2b: Escape `<` in the search dialog's popular-pages JSON payload, so a page title containing `</script>` can no longer terminate the inline script and inject markup.
|
|
252
|
+
- 7ed2b2b: Guard search rendering with a generation counter: a section-pill or locale toggle racing an in-flight remote query no longer appends duplicate or misfiltered result rows.
|
|
253
|
+
- 41bac89: Strip only tag-shaped `<name …>` markup when building the search index: a bare `<` in prose ("costs < 5 credits") no longer deletes everything up to the next `>` — potentially whole paragraphs — from search results.
|
|
254
|
+
- 7e0f413: Stop prepending the site origin to an external `seo.image` URL in the generated catch-all page — `og:image`/`twitter:image` no longer render as `https://docs.example.comhttps://cdn…`.
|
|
255
|
+
- 7b84669: Fix sidebar group route paths when a folder's `index` page is inserted first (the group's path collapsed to `/`, emptying the sidebar for header-tab sections) and when `(group)` folders sit between the folder and its route segments.
|
|
256
|
+
- dfa956e: Make `blume sync` regenerate with a running dev server's URL as the `site` fallback (read from `dev.lock`), instead of silently dropping `site` and OG output from the live runtime.
|
|
257
|
+
- 4ed9f6a: Actually apply the table-cell inline-code nowrap rule: GFM renders `<td><code>` directly, which the descendant-only selector never matched, so inline code in table cells still wrapped.
|
|
258
|
+
- 9d60b00: Honor top-level `hidden` and `noindex` frontmatter as shorthands for `sidebar.hidden` and `seo.noindex` — the schema accepted both but nothing read them.
|
|
259
|
+
|
|
260
|
+
## 0.6.1
|
|
261
|
+
|
|
262
|
+
### Patch Changes
|
|
263
|
+
|
|
264
|
+
- 54099c6: Always-on inline code highlighting and block math; remove their config flags. `markdown.code.inline` and `markdown.math` are gone. Inline `` `code{:lang}` `` highlighting now always runs — it only fires on the explicit `{:lang}` marker, so plain inline code is untouched and there was nothing to opt out of. Math is now always on but **block-only** (`$$…$$`): a bare `$` (currency, shell, code) is always left as literal text, which is exactly why the flag existed, so there's no longer a `$`-in-prose caveat to gate. The `<Math>` component and KaTeX's stylesheet are still only shipped when a page actually uses `$$` — now detected from content instead of a config toggle — so a math-free site pays nothing. Inline `$…$` math is no longer supported (the single-dollar delimiter is reserved for literal text).
|
|
265
|
+
- 7999013: Redesign the generated `/changelog` timeline and paginate it by major version. The page now renders as a focused, full-width column — no sidebar or table of contents — and each release heading links to that release's own page, so an entry is both a timeline line and a shareable permalink. When the releases follow semver and span more than one major, older majors collapse behind a **Show N.x releases** button that reveals the next-oldest major one click at a time (detected automatically; tolerates scoped monorepo tags like `pkg@2.0.0`). It's progressive enhancement — every release stays in the page HTML, RSS feed, and search index, so no-JS readers and crawlers still get the full history.
|
|
266
|
+
- 5adcc8a: Add rich per-field editor docs to `blume.config.ts`. `defineConfig` gains a comprehensive JSDoc overview, and its argument is now a hand-documented `BlumeConfig` type tree so every config field — theme, navigation, content sources, search, AI, SEO, OpenAPI, i18n, and more — shows a hover description and default value with autocomplete. A compile-time guard keeps the documented type structurally in sync with the Zod schema (still the single source of validation truth), so the two can't drift. Type-only change; runtime behavior is unchanged.
|
|
267
|
+
- 3a6e794: Fix `output: "server"` builds deploying a 404. The Vercel/Netlify adapters write their deploy bundle relative to the Astro project root, which Blume points at the hidden `.blume/` runtime — so the bundle (`.vercel/output`, `.netlify/`) landed at `.blume/.vercel/output`, where the platform never looks, while `dist/` held only the client assets (no root page, no function). `blume build` now surfaces a server adapter's bundle up to the real project root, writes deploy artifacts (robots.txt, sitemap.xml, llms.txt, …) into the served static dir, and adds the surfaced dir to `.gitignore`. Vercel (and any Build Output API host) then picks it up with zero config — an imported Blume project deploys on the default Astro settings. Node/Cloudflare emit into `dist/` and are unaffected.
|
|
268
|
+
|
|
269
|
+
## 0.6.0
|
|
270
|
+
|
|
271
|
+
### Minor Changes
|
|
272
|
+
|
|
273
|
+
- 3dcd5b2: Emit `agent-readability.json` at the site root: a manifest that indexes the project's agent-facing surface so agents can discover and cite the docs without scraping HTML. It lists the raw-Markdown mirror pattern (with content negotiation), `llms.txt`/`llms-full.txt`, the MCP server and its `.well-known/mcp.json` discovery doc, the Ask AI endpoint, the sitemap, and RSS feeds — including only the ones actually enabled. It also echoes the `seo.contentSignals` usage policy and the configured source repository. URLs are absolute when `deployment.site` is set and root-relative otherwise.
|
|
274
|
+
|
|
275
|
+
On by default; disable with `seo.agentReadability: false`. As with `sitemap.xml` and `robots.txt`, a file you ship in `public/` takes precedence.
|
|
276
|
+
|
|
277
|
+
- 44646d2: Add `navigation.featured` — pinned links rendered above the sidebar sections. Each takes a `label`, an `href` (external URL or internal route), and an optional `icon`, and appears on every route and breakpoint, outside the tab-scoped sidebar tree. External links open in a new tab with an indicator; internal targets are validated against your pages at build time, and unknown icons warn like anywhere else.
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
export default defineConfig({
|
|
281
|
+
navigation: {
|
|
282
|
+
featured: [
|
|
283
|
+
{ label: "Blog", href: "https://example.com/blog", icon: "newspaper" },
|
|
284
|
+
{ label: "Contact", href: "/contact", icon: "headphones" },
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
This restores a common Mintlify layout where standalone destinations (blog, changelog, support) sit at the top of the sidebar rather than folding into the generated content tree.
|
|
291
|
+
|
|
292
|
+
- 3dcd5b2: Declare `Content-Signal` usage preferences in the generated `robots.txt`. Blume now emits a `Content-Signal` line **on by default** with every signal set to `yes` — `search` (traditional and AI search indexing), `ai-input` (grounding / RAG at answer time), and `ai-train` (model training) — matching its stance that docs are open to humans and agents alike:
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
User-agent: *
|
|
296
|
+
Content-Signal: search=yes, ai-input=yes, ai-train=yes
|
|
297
|
+
Allow: /
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Tune it with `seo.contentSignals`. Restrict individual signals — the rest stay `yes`:
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
export default defineConfig({
|
|
304
|
+
seo: {
|
|
305
|
+
contentSignals: { aiTrain: false }, // → search=yes, ai-input=yes, ai-train=no
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Or set `contentSignals: false` to drop the declaration entirely. Existing sites that ship their own `public/robots.txt` are unaffected — Blume never overwrites it.
|
|
311
|
+
|
|
312
|
+
### Patch Changes
|
|
313
|
+
|
|
314
|
+
- 0b729bc: Redesign the Ask AI assistant. The trigger is now a ghost chat-icon button on the far right of the header, and it opens a full-height docked side panel (in the style of `vercel.com/docs`): on desktop the docs content shrinks to make room and the table of contents hides while the panel is open; on smaller screens it's a full-width overlay. The panel renders answers as Markdown, streams responses, supports a `⌘I` / `Ctrl+I` toggle, and has copy/clear/close controls. The input is a single flush textarea.
|
|
315
|
+
|
|
316
|
+
Add `ai.ask.suggestions` — empty-state prompts shown before the first question, each a clickable `{ label, icon? }` chip.
|
|
317
|
+
|
|
318
|
+
Improve grounding quality:
|
|
319
|
+
|
|
320
|
+
- Retrieval now injects the section of a page most relevant to the question instead of always slicing the page head, so a long page's below-the-fold content is reachable.
|
|
321
|
+
- Ask AI grounds on Markdown (code blocks preserved) rather than search-flattened plain text, so the model can answer from fenced examples the docs actually contain.
|
|
322
|
+
- The model cites sources as Markdown links, rendered as small source pills that navigate to the cited page.
|
|
323
|
+
|
|
324
|
+
Remove the "Ask AI about this page" entry from the page actions menu.
|
|
325
|
+
|
|
326
|
+
- 923877e: Exclude dependency, output, and cache trees from the generated Astro content collection. The content-layer glob previously only skipped `node_modules`, so a `.`-rooted `content.root` re-ingested build output — for example a prior `dist/*.mdx` render — and crashed the build in rolldown with an unresolvable `astro:content-layer-deferred-module` import. It now mirrors the content scan's baseline ignores (`node_modules`, `.git`, `.vercel`, `dist`, `.next`, `.turbo`, `.cache`), while the runtime directory (`.blume`, or a custom `distDir`) stays excluded precisely by the existing output-dir handling.
|
|
327
|
+
- 3312c07: Check the dev lock before regenerating `.blume/`, and record the server's port in it. A second `blume dev` previously regenerated the runtime (with its own port baked in) before noticing the lock, so even a refused invocation churned the running server's generated files on its way out; it now refuses before touching anything. The lock file (`.blume/dev.lock`) stores `{pid, port}` — updated with the actual bound port if Vite bumps a busy one — so the refusal messages from `dev`, `build`, `check`, and `eject` point at the live server's URL (e.g. "A `blume dev` server is already running at http://localhost:3001 — reuse that server"), steering callers (especially agents) toward reusing the running server instead of killing it.
|
|
328
|
+
- 1081989: Add a "Copy Codex command" option to the Connect to MCP menu, alongside the existing Claude Code, Cursor, and VS Code installs. It copies `codex mcp add <name> --url <url>` for the hosted MCP server. Also make `PageActions` labels fall back to the English defaults per-key, so a string missing from a translation renders the default instead of coming out blank.
|
|
329
|
+
- 1081989: Improve the page-actions dropdowns (Export, Open in chat, Connect to MCP). Only one opens at a time — opening one closes the others. A menu flips above its trigger when opening downward would run past the viewport bottom (and there's room above), so the Connect to MCP menu no longer gets clipped. Menus keep a padding gap from the viewport edge and size to their content instead of the narrow sidebar column, so longer items like "Copy Claude Code command" no longer wrap.
|
|
330
|
+
- 923877e: Default-ignore never-content directories during the content scan. The filesystem source now always skips `node_modules`, `.git`, `.blume`, `.vercel`, `dist`, `.next`, `.turbo`, and `.cache` — in addition to the user's `content.exclude`, and even when `exclude` is overridden. Previously a broadly-scoped `content.root` (`"."` or an app directory that also holds `node_modules`/build output — the common shape when migrating a docs app that lives at the repo or app root) would glob thousands of stray Markdown files out of dependencies and build artifacts. `content.root` still defaults to `docs/`, where this rarely bit.
|
|
331
|
+
- 4ff9c26: Fix the Vercel (`output: "server"`) build failing in `astro:build:done` with `dist/server/entry.mjs does not exist`. Blume declared its render-time SSR externals under a user-owned `vite.environments.ssr` block, which collides with the internal environment Astro 7 builds the server under and detaches the adapter's server entrypoint from the rolldown input — so the SSR entry was emitted as `index.mjs` and the Vercel adapter couldn't find `entry.mjs`. The SSR externals now go through the legacy `vite.ssr.external` key (the `prerender` environment is Astro-only and stays under `environments`).
|
|
332
|
+
- 923877e: Widen the dev watcher's ignore set to cover build and deploy caches. Alongside `.blume`, `.git`, and `node_modules`, the recursive content watcher now also ignores `.vercel`, `dist`, `.next`, `.turbo`, and `.cache`, sharing one canonical directory list with the content scan so the two never disagree about what counts as content. This keeps churn from build output and framework caches from needlessly re-triggering a rescan during `blume dev`.
|
|
333
|
+
|
|
334
|
+
## 0.5.4
|
|
335
|
+
|
|
336
|
+
### Patch Changes
|
|
337
|
+
|
|
338
|
+
- 4de9522: Add a `blume-update-docs` agent skill for keeping a Blume docs site in sync with the product it documents. A scheduled agent run audits recently merged PRs, changelogs, config schemas, and CLI help against the docs, updates only pages that are factually stale (feature-flagged work is ignored), verifies with `blume build`, and opens or updates a `blume/*` pull request — or reports a clean no-op. Install it with `npx skills use haydenbleasel/blume@blume-update-docs`; it also ships in the package at `node_modules/blume/skills`. The new `/docs/advanced/skills` page documents all shipped skills.
|
|
339
|
+
- ac4dd2a: Fix code blocks rendering flush against the edge (no horizontal padding, inline, unscrollable) inside content components — `<Steps>`, `<Callout>`/`:::note`, `<Card>`, `<Accordion>`, `<Expandable>`, `<Panel>`, `<Update>`, `<Tabs>`, and `<CodeGroup>`. The rule that gives code blocks their inset opted out of every `not-prose` subtree, but only the API request panel actually owns its own code layout — every other component wraps its chrome in `not-prose` while still hosting real prose content. The exclusion now targets just the API panel, so code keeps its standard padding everywhere else. The Component source pane and API request panel are unchanged.
|
|
340
|
+
- 3ac07da: Add a global `min-width: 0` base reset so flex and grid children shrink to their container instead of forcing horizontal overflow. This defuses the common case where a long or truncating child (a code snippet, a long nav label) pushes its row — and the whole page — past the viewport edge on narrow screens, and removes the need for the per-element `min-w-0` overrides the components previously carried. The base layer also now defaults interactive controls (`button`, `[role="button"]`) to `cursor: pointer` unless disabled, and enables `text-rendering: optimizeLegibility`.
|
|
341
|
+
- d8a413e: Harden remote OpenAPI spec loading and stop a failed fetch from shipping a dead reference tab. Remote (`http(s)`) specs are now fetched defensively — bounded by a per-attempt timeout, retried with backoff on transient failures (network errors, timeouts, 408/425/429/5xx, honoring `Retry-After`), sent with a User-Agent, routed through an HTTP(S) proxy when `HTTP(S)_PROXY` is set (Node's `fetch` ignores proxy env vars on its own, the classic "curl works but the build doesn't" gap), and cached on disk so a transient outage falls back to the last good copy with a warning instead of dropping the reference. A spec that still can't be loaded is now an error in `build` (a configured reference otherwise ships a nav tab pointing at a route that was never generated — a silent 404) while staying a warning in `dev` so offline work keeps running.
|
|
342
|
+
- 9afab11: Split the `logo` config into an `image` mark and a `text` wordmark so a site can show an image-only logo, a text-only logo, or both. The object form is now `{ image, text, href }`: `image` takes the same value as the string shorthand (a single path, or `{ light, dark, alt }` for themed artwork), and `text` controls the wordmark independently — omit it to fall back to the site title (the previous behavior), set `text: ""` to render the mark alone (handy when the logo image already carries the wordmark), or set `text` with no `image` for a text-only logo. The bare-string shorthand (`logo: "/logo.svg"`) is unchanged; the old flat object form `{ light, dark, alt }` now nests under `image`.
|
|
343
|
+
- 6d4ae0d: Restyle collapsible sidebar group headers to sit back visually: the group `<summary>` now renders in the muted foreground color and brightens to the full foreground on hover, matching the treatment of leaf nav links. The active-page group header still resolves to the foreground color and bold weight so the current section stays legible.
|
|
344
|
+
- fdf6863: Fix tab navigation on routes that own no sidebar group. A page under a tab whose source produced no sidebar sections — a standalone page like the generated `/changelog` timeline — now renders an empty sidebar instead of falling back to the full tree, which had leaked every other tab's sections (e.g. the OpenAPI operations) onto the page. Chrome-only pages rendered via `PageLayout` (a landing page with tabs but no sidebar) also gain a working mobile navigation drawer: the header's nav toggle now appears whenever there are tabs — not only when a sidebar is present — and opens a slide-in tabs drawer below `lg`.
|
|
345
|
+
|
|
346
|
+
## 0.5.3
|
|
347
|
+
|
|
348
|
+
### Patch Changes
|
|
349
|
+
|
|
350
|
+
- 72ce7c8: The generated Ask AI endpoint now validates message shapes, not just the array size. Previously any JSON array of 1–40 items was forwarded to `streamText` verbatim, so a caller could POST a `role: "system"` message and repurpose the unauthenticated endpoint as a general LLM proxy on the site owner's API key. Each message must now be `{ role: "user" | "assistant", content: string }`, and the array is rebuilt so only those two fields ever reach the model.
|
|
351
|
+
- 9d6bf61: Ask AI and search now work when `deployment.base` has no trailing slash. Astro passes the base through as-is, so `base: "/docs"` made the Ask AI island POST to `/docsapi/ask` (every question failed with a 404), page grounding send `//guide` paths, and the generated search clients request `/docsblume-search.json` / `/docsapi/search` / `/docspagefind/pagefind.js`. All island and generated-client URL joins now go through a shared helper that normalizes the trailing slash.
|
|
352
|
+
- c0dcfc1: A round of CLI and generated-endpoint hardening: config validation now reports every issue in one failing run instead of one per rerun; a second concurrent `blume dev` refuses instead of silently sharing (and corrupting) `.blume/` with the first; the dev-lock liveness probe treats an `EPERM` (process alive under another user) as locked instead of stale; an explicit `/index` sidebar ref resolves to the root route instead of an empty link; the generated Mixedbread search endpoint returns an empty result for malformed JSON instead of a 500; malformed percent-encoding in an asset URL 404s instead of throwing in middleware; and a `client:media` override value with quotes or newlines can no longer break the generated wrapper component.
|
|
353
|
+
- c9c12d8: `<Color.Item>` dual-value swatches now actually switch in dark mode. The dark-mode style targeted a `.dark` class that Blume never sets — dark mode is `data-theme="dark"` on `<html>` — so `value={{ light, dark }}` always rendered the light color. The selector now matches the real dark-mode attribute.
|
|
354
|
+
- a1797e8: A batch of component and markdown fixes: code-fence titles may now contain the other quote character (`title="foo's file.ts"` no longer mangles into `file.ts"`); package-manager install tabs no longer rewrite the page hash when clicked (clobbering the heading anchor the reader arrived with); search-dialog highlighting can't mark inside HTML entities anymore (querying "amp" corrupted excerpts containing `&`); a failed search-index load retries on the next open instead of disabling search until reload; the `useAskAI` hook surfaces an error message instead of streaming a 4xx/5xx body as the assistant's answer; copy buttons can't get stuck on "Copied!" after a double-click; the Cursor MCP install deeplink URL-encodes its base64 config; generated cURL samples survive apostrophes in example bodies and Python samples no longer rewrite `true`/`false`/`null` inside string values; Mermaid diagrams disconnect their theme observer when removed and drop stale renders from rapid theme toggles; and a `<blume-tabs>` moved in the DOM re-attaches its sync/hash listeners.
|
|
355
|
+
- 8b1de21: Folder `meta.ts` files now apply to every locale under the `dot` i18n parser. Non-default locales looked meta up under a locale-prefixed key (`fr/guides`) that only exists in the `dir` layout, so with `parser: "dot"` — where translations sit next to the originals — translated sidebars silently lost their configured titles, ordering, icons, and collapsed state and fell back to humanized folder names. Locale-prefixed lookups now only happen under the `dir` parser.
|
|
356
|
+
- ebadad0: The Fumadocs migrator no longer deletes a `meta.json` whose conversion was skipped. When a `docs/<dir>/meta.ts` already existed at the destination, the migrator skipped writing the converted meta but still removed the source `meta.json` — permanently losing its title and page ordering. The source file is now kept alongside a warning telling you to merge it by hand, matching how page collisions already behave.
|
|
357
|
+
- 27b3c71: Link validation no longer flags Markdown link syntax shown inside inline code. Prose like `` use `[label](/page)` syntax `` registered `/page` as a real link, and since broken internal links are build errors, any page demonstrating link syntax failed `blume validate`. Inline code spans are now masked out (with column positions preserved) before link extraction, matching how component-tag extraction already behaves.
|
|
358
|
+
- d8d458c: MCP server URLs now honor a subpath `deployment.site`. `search_docs`/`list_pages` result URLs and the `/.well-known/mcp.json` server address were built with `new URL(route, site)`, which drops the path of a base like `https://acme.com/docs` — pointing agents at nonexistent root-level pages while `llms.txt` linked correctly. Both now concatenate like the rest of the AI surface.
|
|
359
|
+
- fc9a4a1: The `mdx-remote` content source no longer sends `GITHUB_TOKEN` to non-GitHub hosts. Every fetch — including files enumerated from a custom `url` base pointing at an arbitrary server — attached `Authorization: Bearer $GITHUB_TOKEN`, leaking the repo credential to whatever host the source was configured against. The token is now only attached for `api.github.com` and `raw.githubusercontent.com`.
|
|
360
|
+
- edf6fef: `blume dev` on a migrated Mintlify project (`content.root: "."`) no longer loops or fails to load. A migrated project keeps its pages at the project root, which also contains Blume's generated `.blume/` output — and the dev server rewrites files under `.blume/` (its data store, content-module manifests, self-hosted fonts, and the regenerated `src/generated/*` data modules) as it renders. Two watchers fed on those writes:
|
|
361
|
+
|
|
362
|
+
- The **filesystem content source**'s recursive `fs.watch` saw every `.blume/` write and re-ran a full rescan + runtime regeneration, whose own writes landed back under `.blume/` and re-fired the watcher — a self-sustaining loop that spammed the console with repeating `data-store.json` reloads and, by rewriting the runtime mid-render, broke Astro's dev module graph (`Failed to load url astro:server-app.js`). This is the same storm the Mintlify bridge source was already hardened against; the fix is now shared, so the filesystem source ignores events under `.blume/`, VCS/dependency trees, and every excluded directory.
|
|
363
|
+
- Astro's content-layer `docs` glob loader is rooted at the project directory, so it logged `No entry type found` / `Reloaded data` for every write Astro makes under its own cache dir (`.blume/.astro/`). The generated dev config now keeps Vite's file watcher out of that cache dir.
|
|
364
|
+
|
|
365
|
+
As a defence in depth, dev regeneration is now single-flighted: a burst of watch events (or any future storm) coalesces into one trailing scan instead of piling up overlapping scans, which on a large project could outlast the debounce and exhaust the heap (the loop above eventually OOM-crashed the dev server).
|
|
366
|
+
|
|
367
|
+
Normal projects, whose content root sits outside `.blume/`, were unaffected.
|
|
368
|
+
|
|
369
|
+
- c57377e: Migrator and search-sync cleanups: stripping old-framework imports no longer collapses double blank lines inside code fences (the gap-collapse now targets only the removal seams, across the Mintlify, Fumadocs, and Starlight migrators); the Nextra migrator repoints `package.json` scripts at Blume and gitignores `.blume/`/`dist/` like the Fumadocs one (previously `npm run dev` still launched Next against the gutted content tree); the Mintlify migrator's two local path-containment checks now use the shared `isInsideRoot`, closing a Windows-only gap where a cross-drive `$ref`/snippet path escaped the project root; and the Typesense and Orama Cloud syncs now carry the documented `locale` facet so i18n sites can filter hosted results per language.
|
|
370
|
+
- 5fc39d4: `blume migrate mintlify` now keeps images referenced only by page content resolvable. Asset relocation previously considered just `/images` plus paths named in the config (logo, favicon, backgrounds) — a page using `` or `<img src="/img/logo.svg">` silently 404'd after migration, since Mintlify serves every top-level directory at the site root but Blume only serves `public/` and `content.assets` mounts. Root-absolute asset references in content are now collected during the rewrite and their directories added to `content.assets`.
|
|
371
|
+
- ad120e0: `blume migrate mintlify` now removes the source `docs.json`/`mint.json` after writing `blume.config.ts`. Leaving the Mintlify config on disk kept the project a bridge-mode candidate: any later run without a loadable `blume.config.*` would silently fall back to serving the un-migrated Mintlify project. The foreign config is only deleted after the Blume config is safely written, so a mid-migration failure never leaves the project with neither.
|
|
372
|
+
- ff6b5d4: A dangling Mintlify snippet import no longer aborts the whole migration. `blume migrate mintlify` crashed with a raw `ENOENT` when any page imported a snippet file that doesn't exist — after some pages were already rewritten in place and before `blume.config.ts` was written, with no hint which page failed. The affected page (missing snippet or circular snippet chain) is now left unconverted with a warning naming both the page and the snippet, and the rest of the migration completes.
|
|
373
|
+
- e796b18: Migrators now convert nested callouts correctly. The callout-to-directive rewrite found its close tag with a flat string search, so `<Warning>… <Info>…</Info> …</Warning>` left the inner component unconverted (failing the build — Blume ships no `<Info>`), and same-tag nesting closed at the inner tag, leaking a stray `</Note>` into the page (an MDX compile error). Close tags are now matched depth-aware, inner bodies are converted recursively, and outer directive fences grow (`::::`) so nested `:::` blocks parse as containers. Applies to the Mintlify, Fumadocs, Nextra, and Starlight migrators.
|
|
374
|
+
- f38e7dd: Circular OpenAPI schemas no longer crash the build with a stack overflow. `typeLabel` recursed forever on arrays whose `items` `$ref` pointed back at the same schema (it resolved the ref before recursing, bypassing its own `$ref` shortcut — array-of-ref types now label as `Name[]`), and `objectProperties` followed mutually-recursive `allOf` chains with no visited-ref guard, which also took down `exampleValue` and every generated request sample. Both now terminate on any cyclic spec.
|
|
375
|
+
- 132f6a9: OpenAPI descriptions that start a line with `import` or `export` no longer crash the build. Operation and overview descriptions are embedded as markdown in generated MDX pages, and MDX parses lines beginning with those keywords as ESM — so common API prose like "import the SDK and call the endpoint" failed compilation with an acorn parse error. The keyword's first letter is now entity-escaped alongside the existing `<>{}` neutralization; the rendered text is unchanged.
|
|
376
|
+
- 2ed8345: Leading/trailing slashes in a frontmatter `slug` or a source `prefix` no longer produce malformed routes. `slug: /getting-started` mapped to `//getting-started` and `slug: guides/` to `/guides/` — routes nothing could link to, tripping false `BLUME_BROKEN_LINK`/`BLUME_NAV_MISSING_PAGE` diagnostics and diverging translation keys under i18n. Slugs and prefixes are now trimmed of surrounding slashes and empty route segments are dropped; dotted slug segments like `releases/v1.2` are preserved.
|
|
377
|
+
- 5807c22: `SourceEntry.slug` is now honored. The custom-source SPI documents `slug` as "logical route input; defaults to `ref` if omitted", but normalization only ever read `ref` — an adapter returning `{ ref: "abc123.md", slug: "custom/path" }` routed to `/abc123` with no diagnostic. Frontmatter `slug` still wins over the adapter-supplied one.
|
|
378
|
+
- e0bc986: `theme.accent`, `theme.action`, and `theme.backgroundDecoration` now actually apply in dark mode. The base stylesheet's `:root[data-theme="dark"]` block outranked the `:root` config tokens on CSS specificity, so dark mode silently kept its neutral defaults — `accent: "teal"` gave a teal light mode and a near-white dark mode, contradicting the documented "light and dark share one accent". The generated config CSS now re-declares the mode-shared tokens (accent + foreground, action, background decoration) in a dark-scoped block; `accentDark` still takes precedence when set.
|
|
379
|
+
- a45d842: Hardened theme and OG rendering against hostile-shaped config and content values. A `theme.accent` (or icon name/library) matching an `Object.prototype` member like `constructor` resolved a function up the prototype chain — stringifying into the generated CSS or crashing icon resolution mid-build with no pointer to the offending page; lookups are now own-property only. A malformed hex accent (`#12345`) no longer throws a native error inside the OG renderer and fails the build — it falls back to the default accent. The OG logo viewBox parser now also accepts single-quoted attributes and non-zero origins, so wide wordmarks keep their aspect ratio instead of being squeezed into a square.
|
|
380
|
+
|
|
381
|
+
## 0.5.2
|
|
382
|
+
|
|
383
|
+
### Patch Changes
|
|
384
|
+
|
|
385
|
+
- 34ccd52: `blume dev` in Mintlify bridge mode is no longer slow and noisy. Bridge mode roots content at the project directory, which contains Blume's generated `.blume/` output — and the dev server rewrites `.blume/.astro/*` (its data store and font cache) on every request. Two things fed on those writes:
|
|
386
|
+
|
|
387
|
+
- The Mintlify source's recursive `fs.watch` saw them and re-ran a full rescan + runtime regeneration, whose own writes landed back under `.blume/` and re-fired the watcher — a self-sustaining storm that stalled page renders (8–26s). The watcher now ignores events under `.blume/`, `node_modules`, and other non-content trees.
|
|
388
|
+
- Astro's content-layer `docs` collection was rooted at the project directory even though, in bridge mode, every page renders through the staged collection — so its glob loader watched `.blume/.astro/fonts/` and warned `No entry type found` for each `.woff2` on every rebuild. The `docs` collection now globs nothing when no filesystem source feeds it (glob-pattern negations can't exclude a subtree from Astro's watcher, so an empty pattern is the only reliable fix), which also avoids double-loading the staged bodies under `.blume/content`.
|
|
389
|
+
|
|
390
|
+
Normal (non-bridge) projects were unaffected, since their content root sits below `.blume/`.
|
|
391
|
+
|
|
392
|
+
- b47f927: `blume migrate mintlify` now scaffolds the project files a config-only Mintlify repo lacks. Mintlify docs are driven by `docs.json`/`mint.json` and ship no npm manifest, so a fresh migration previously left nothing to run `blume dev` with. The migrator now writes a minimal, runnable `package.json` with `blume` pinned as a dependency and `dev`/`build`/`doctor` scripts (derived name, `private: true`), plus a `.gitignore` for Blume's generated `.blume/` runtime and `dist/` build output — so `npm install && npm run dev` works immediately and the generated output stays untracked. Both are idempotent: an existing `package.json` is left untouched and an existing `.gitignore` is only extended. The `package.json` template is now shared with `blume init`.
|
|
393
|
+
|
|
394
|
+
## 0.5.1
|
|
395
|
+
|
|
396
|
+
### Patch Changes
|
|
397
|
+
|
|
398
|
+
- 348b6f4: Dropped `navigation.sidebarVariants`, an unused per-partition sidebar mechanism. It was built, validated, and shipped in the data module, but no layout ever read it — the sidebar has always been scoped at render by the active **tab** via `sidebarForRoute`, and that remains the model. The Mintlify migrator emitted one variant per page (each carrying the full section sidebar), which is what ballooned a large migrated site's `blume.config.ts` to ~4.9 MB / 126k lines; it no longer emits any, so migrated configs shrink to a few KB. The `sidebarVariants` config field, its schema, the `NavSidebarVariant` type, and the variant folds in nav diagnostics are all removed.
|
|
399
|
+
|
|
400
|
+
Because `navigation` config is `.strict()`, a stale config that still carries a `sidebarVariants` key will now fail validation — drop the key or re-run `blume migrate mintlify` to regenerate a clean config.
|
|
401
|
+
|
|
402
|
+
- 1d5937c: `blume migrate mintlify` now rewrites Mintlify accordions to Blume's shape. Mintlify wraps `<Accordion title="…">` items in an `<AccordionGroup>`, whereas Blume inverts that: `<Accordion>` is the container and each item is an `<AccordionItem title="…">`. The migrator previously left both tags untouched, so migrated pages that used accordions failed the MDX build outright — Blume ships no `<AccordionGroup>` component, so rendering threw `Expected component AccordionGroup to be defined` — and the nested `<Accordion title=…>` items lost their title and expand behavior. The group is now remapped to `<Accordion>` and every item to `<AccordionItem>` (preserving `title`, `icon`, and other props), so those pages build and render correctly.
|
|
403
|
+
- 8ac7101: `blume migrate mintlify` now drops dynamic (wildcard/param) redirects instead of emitting ones that break the build. Mintlify's `:slug*`/`:id` redirect params were translated to Astro `[...slug]`/`[id]` segments, but Blume redirects are static path-to-path — a dynamic destination matches no route, so Astro aborted the entire build (`The destination "…/[...slug]" does not match any existing route in your project`). Such redirects are now skipped, and the migrator emits a warning that names the dropped sources and points to host-level redirect files (`_redirects`, `vercel.json`), which do support wildcards. Static redirects are unaffected, so the migrated site builds.
|
|
404
|
+
|
|
405
|
+
## 0.5.0
|
|
406
|
+
|
|
407
|
+
### Minor Changes
|
|
408
|
+
|
|
409
|
+
- 48d68f4: Icons now resolve from the full open icon libraries — **Font Awesome** (free), **Lucide**, and **Tabler**, the three Mintlify exposes — instead of a hand-curated subset. Resolution happens at build time and inlines zero-JS SVG, so there's no runtime CDN fetch (unlike Mintlify) and unused icons cost nothing on the client.
|
|
410
|
+
|
|
411
|
+
- New `icons.library` config picks the default library for bare names (`"lucide"` default, or `"fontawesome"` / `"tabler"`).
|
|
412
|
+
- `iconType` selects a Font Awesome style (`solid`, `regular`, `brands`); Pro-only styles (`light`, `thin`, `duotone`, `sharp-solid`) aren't in the free data and fall back to solid.
|
|
413
|
+
- An explicit `library:name` prefix (`fa6-brands:github`, `lucide:rocket`, `tabler:heart`) overrides the default per icon, so libraries can be mixed.
|
|
414
|
+
- Font Awesome brand names resolve even under the solid default (`icon="github"` finds the brands set).
|
|
415
|
+
- The Mintlify migrator sets `icons.library: fontawesome` (Mintlify's default), so a migrated site's existing Font Awesome icon names — previously mostly unresolved — now render.
|
|
416
|
+
|
|
417
|
+
The curated inline-SVG set and its FontAwesome alias map are gone; a small internal set is kept only for Blume's own client-side chrome (copy/search/etc.). The five Iconify data packages are build-time dependencies (server-side only), so they add nothing to shipped pages.
|
|
418
|
+
|
|
419
|
+
- 6d17781: Add `--isolated` to `blume build` and `blume check` so you can build/verify while a `blume dev` server is running. Both commands regenerate the shared `.blume/` runtime, so running them against a live dev server would corrupt it — `build` refused and `check` (which had no guard) silently corrupted it. `--isolated` relocates the whole generated runtime — and, for `build`, its `dist/` output — to a throwaway `.blume-verify/` sibling (auto-gitignored), leaving the dev server's `.blume/` and your real `dist/` untouched. Isolated builds skip the deploy post-steps (search index, hosted-provider sync, `llms.txt`, sitemap/robots, redirects) since a verify only needs to confirm the site compiles and renders. `check` now also refuses a live dev server when not isolated, the refusal message points at `--isolated`, and `BLUME_RUNTIME_DIR` lets plain `build`/`check` isolate without the flag (useful for coding agents verifying changes alongside an open dev server).
|
|
420
|
+
- e023325: Rebuild OpenAPI support with a native, Blume-rendered API reference (default `renderer: "blume"`). Blume now parses each spec with Scalar's OpenAPI parser (upgrading Swagger 2.0 / OpenAPI 3.0 to 3.1) and lowers every operation into a real content page — so operations get their own route (`/reference/<tag>/<operation>`), a tag-grouped, tab-scoped sidebar with colour-coded method badges, and inclusion in site search, `llms.txt`, and Open Graph, just like any hand-written doc. Operation pages use a two-column layout: parameters and schema tables on the left, a Scalar-style Request/Response panel (language tabs + copy, status-tabbed response examples) on the right in place of the table of contents. New `openapi` options: `renderer` (`"blume"` | `"scalar"`), `codeSamples`, and `expandSchemas`. Set `renderer: "scalar"` to keep the embedded Scalar reference; AsyncAPI continues to render through Scalar.
|
|
421
|
+
- 1780373: Added Mintlify-compatible `<ParamField>`, `<ResponseField>`, and `<RequestField>` components for documenting request/response fields (CLI flags, SDK arguments, endpoint parameters). Each renders a labeled field row — name, type, and `required`/`deprecated`/`default` badges styled to match the native OpenAPI reference — with the description taken from the element's body (rich MDX, including a nested `<Expandable>`). `<ParamField>` reads the field's location from the attribute that names it (`path`, `query`, `header`, `body`, or a plain `name`) and shows it as a small label. Previously these had no Blume equivalent, so ~488 uses across a migrated Mintlify site failed to compile as undefined MDX components; they now render as-is in both a migrated project and live Bridge mode. The Mintlify migrator no longer flags them (or points at the OpenAPI reference for surfaces a spec doesn't cover); Mintlify's `<Update>` changelog component remains flagged since Blume's changelog is frontmatter-driven.
|
|
422
|
+
|
|
423
|
+
### Patch Changes
|
|
424
|
+
|
|
425
|
+
- 515277c: Page frontmatter now accepts an `authors` field (a name, an array of names, or an array of author objects with a name plus optional avatar/url and any extra fields). Blume's `pageMetaBaseSchema` is `.strict()`, so a page carrying `authors` — common on blog/changelog content, including sites moved over with `blume migrate mintlify` — previously failed frontmatter validation entirely (`BLUME_FRONTMATTER_INVALID`) and dropped out of the scan. The field is preserved as-is (not yet rendered), so those pages validate and keep their author metadata.
|
|
426
|
+
- 0897ca9: Expanded the built-in icon set and its FontAwesome/Lucide synonym map so far more icon names resolve. The curated set grows from 53 to 158 icons (common docs glyphs — `gauge`, `layers`, `shield`, `cpu`, `database`, `terminal`, `cable`, `file-text`, `folder-tree`, chart/cloud/list/user variants, and more), and the alias map grows from 15 to 177 entries mapping FontAwesome names to their closest Blume icon (`shield-halved` → `shield-half`, `layer-group` → `layers`, `arrows-rotate` → `refresh-cw`, `wand-magic-sparkles` → `wand-sparkles`, `user-shield` → `shield-user`, `gauge-high` → `gauge`, …). Sites migrated from FontAwesome-based Mintlify projects now render icons on Cards, Steps, and sidebar groups that previously resolved to nothing, and several icons referenced by Blume's own docs (`cable`, `file-text`, `folder-tree`) now render. Icons are inlined as zero-JS SVG server-side, so unused entries add nothing to the client payload.
|
|
427
|
+
- 86761c1: The Mintlify migrator now maps `fonts` to `theme.fonts` and stops silently dropping site chrome it can't model. A `fonts.family` (or a `heading`/`body` split) resolves to the matching Blume Google-font slug — `Space Grotesk` → `space-grotesk`, `Geist` → `geist`, and so on — and a family outside Blume's curated set is reported rather than guessed. Header links (`navbar.links`/`navbar.primary`) and footer socials (`footer.socials`), which have no `blume.config` equivalent, are now surfaced as migration warnings (pointing at `navigation.tabs` or a Header/Footer layout override) instead of disappearing. The contextual page menu and last-updated timestamp are already covered by Blume defaults, so they're intentionally treated as no-ops.
|
|
428
|
+
- 5aacd93: The Mintlify migrator now maps `openapi` spec sources onto Blume's native OpenAPI reference instead of silently dropping them. Previously `loadMintlifyConfig` never read a top-level or per-group `openapi` key and skipped `GET /path` endpoint refs, so a site whose entire API reference is a remote spec declared in nav produced no `openapi:` block and no warning. It now walks the navigation tree (plus top-level `openapi` and `api.openapi`) collecting every spec — a string, an array, or a `{ source, directory }` object — dedupes by spec, maps a group's `directory` to the reference's `route`, and emits `openapi: { enabled: true, sources: [...] }`. Endpoint refs are still skipped (the native renderer generates those pages from the spec), and the migration prints a warning listing how many spec sources were mapped so you can verify each path or URL resolves.
|
|
429
|
+
- 07aa14c: The Mintlify migrator now translates path-to-regexp wildcard redirects into Astro's dynamic-segment syntax. Previously `mintlifyRedirects` copied `from`/`to` verbatim, so a `/old/:slug*` → `/new/:slug*` redirect reached Astro's `redirects` unchanged and never matched. Both sides of each redirect are now converted (repeatable params `:name*`/`:name+` → `[...name]`, others → `[name]`), preserving the param name so Astro can substitute it into the destination.
|
|
430
|
+
|
|
431
|
+
## 0.4.0
|
|
432
|
+
|
|
433
|
+
### Minor Changes
|
|
434
|
+
|
|
435
|
+
- dddb157: Add a `<YouTube />` content component for embedding YouTube videos. It renders a responsive, privacy-enhanced (`youtube-nocookie.com`) 16:9 iframe with `loading="lazy"` and ships no client JavaScript. Pass a video `id` or a full `url` (any of the `youtu.be`, `watch?v=`, `/embed/`, `/shorts/`, `/live/` forms), plus an optional `title` and a `start` time in seconds. Available in `.mdx` pages, in `<BlumePage>` embeds, and via `blume add youtube`.
|
|
436
|
+
- 2727bfd: Add `content.assets`: top-level directories served at the site root alongside `public/`. This lets a project keep root-served asset folders in place instead of relocating them under `public/`. The generated runtime serves each mount in dev (Astro only serves `publicDir`) and copies it into `dist/` on build, and link validation resolves asset references against these mounts too.
|
|
437
|
+
|
|
438
|
+
The Mintlify migrator now uses this instead of moving whole asset directories: referenced dirs (e.g. `images/`) stay put and are recorded in `content.assets`, so a migration no longer churns every file under them. Loose top-level asset files (a root `favicon.png`/`logo.png`) still move under `public/`.
|
|
439
|
+
|
|
440
|
+
### Patch Changes
|
|
441
|
+
|
|
442
|
+
- c2ef9a0: Guard the shared `.blume` runtime dir with a dev lock. `blume dev` continuously regenerates and serves `.blume`, so a `blume build` or `blume eject` run in another shell could regenerate or delete it out from under the live Vite server and corrupt the session. `dev` now writes a PID lock, and `build`/`eject` refuse with a clear message while it's held (stale locks from a crashed dev server are ignored). `blume sync` is unaffected — it's designed to refresh content while `dev` is running.
|
|
443
|
+
- b0c592b: Validate a raw `theme.accent` (and `accentDark`/`action`) before writing it into the generated theme CSS and the Scalar OpenAPI theme. A value containing CSS control characters like `;}` could otherwise break out of the declaration and inject rules; such a value now falls back to the default accent. Named presets and normal colors (hex, `rgb()`, `oklch()`, …) are unaffected.
|
|
444
|
+
- c38af59: Fix the grounded **Ask AI** endpoint failing to build. The generated `/api/ask` route lives at `src/pages/api/ask.ts` but imported its retrieval data from `../generated/ask-data.json`, which resolves one directory too high (`src/pages/generated/…`) and doesn't exist. It now climbs two levels (`../../generated/ask-data.json`), matching the other depth-two endpoints, so Ask AI builds under the default (gateway) provider and every grounded backend.
|
|
445
|
+
- 7ac6fc5: Show the error notice, not the raw error body, when an Ask AI request fails. The in-page island streamed `response.body` without checking `response.ok`, so a 4xx/5xx (e.g. a rate-limit or server error) had its error text decoded and rendered as the assistant's answer. Non-OK responses now surface the friendly error message instead.
|
|
446
|
+
- fc4d1c4: Reject a non-numeric `--budget-js` / `--budget-css` on `blume build` instead of silently disabling the performance gate. `Number("250kb")` is `NaN` and `total > NaN` is always false, so a typo'd budget made the check pass no matter the bundle size. The flags are now validated up front and error out like `--output` and `--adapter`.
|
|
447
|
+
- 805eb5b: Anchor config/frontmatter diagnostic positions to whole keys. When locating a Zod issue in the source, a path segment like `title` could match the tail of an unrelated key such as `subtitle:`, pointing the error at the wrong line/column. Key matching now requires a word boundary.
|
|
448
|
+
- aba6f5e: Keep formatted words in a callout's `[label]` title. The title text was gathered only from a paragraph's immediate text children, so any bold, italic, inline-code, or linked word was dropped — `:::note[Read **this** now]` became `Read now`. The label text is now collected recursively, preserving every word.
|
|
449
|
+
- ee6e165: Stop `blume validate` from misreading a route with a dot in its last segment as a missing asset. A link to a real page like `/releases/v1.0` matched the asset-extension heuristic (`.0`) before the route was checked, producing a false `BLUME_BROKEN_ASSET` warning. Link validation now checks the route map first, so a real route always wins over the asset heuristic.
|
|
450
|
+
- 3ad8b84: `blume eject` no longer silently overwrites a customized root `tsconfig.json`. Eject wrote its own `tsconfig.json` unconditionally, clobbering any paths or compiler options you'd tuned, and the confirmation only mentioned `astro.config.mjs` and `src/`. It now leaves an existing `tsconfig.json` in place (writing one only when absent), and the confirmation discloses the `tsconfig.json` and `package.json` changes.
|
|
451
|
+
- 779fa7d: Fix a build crash when a callout directive is empty. An empty `:::note` / `:::` (no body) parses to a node with `children: null`, which the callout plugin spread into an array and threw on — failing the whole page build. Empty callouts now render as an empty `<Callout>` instead of crashing.
|
|
452
|
+
- 543068d: Report the correct column for a Markdown link whose label repeats its target. The link position was found by searching for the target text from the start of the `[label](target)` match, so `[/a/b](/a/b)` pointed at the occurrence inside the label. The column is now taken from the `](` boundary.
|
|
453
|
+
- be9cc25: Contain the Fumadocs migrator to the docs tree. A `pages` entry in a `meta.json` (e.g. `"../../victim"`) could resolve to a file outside the source directory and get `rename`d out of place, and an `<include>../../secret</include>` could read and inline an arbitrary file into the migrated output. Both paths now reject targets that escape the docs root — matching the Mintlify migrator's existing guard — and skip them with a warning.
|
|
454
|
+
- 5e43a64: Fix `blume validate` falsely flagging relative links from index pages. A directory index (`guides/index.mdx`, route `/guides`) has a route that already _is_ its directory, but relative resolution still popped a segment, so a link like `./setup` resolved to `/setup` and was reported as a broken link. Index pages now resolve relative links against their own route.
|
|
455
|
+
- 6b2e84a: Reject a `--content-dir` on `blume init` that escapes the project. The value is joined into every scaffolded file path, so `--content-dir ../../foo` would write seed content outside the target directory. An absolute or `../`-escaping content dir now errors out.
|
|
456
|
+
- d9d1057: Skip island files whose name isn't a valid identifier instead of emitting a broken module. A file like `islands/Time-Picker.tsx` starts uppercase but its name is used verbatim as an unquoted object key in the generated island map (`Time-Picker: I0`), which is a syntax error that failed the entire build with no pointer to the offending file. Island names are now validated as full PascalCase identifiers (letters, digits, underscores) and non-conforming files are skipped with a warning, like lowercase names already were.
|
|
457
|
+
- 0ad5cb7: Don't truncate `--json` diagnostics output in CI. `blume doctor --json` and `blume validate --json` wrote the JSON payload and then called `process.exit`, which doesn't flush a piped stdout — so a large payload could be cut off into invalid JSON that the consumer couldn't parse. The commands now drain stdout before exiting non-zero.
|
|
458
|
+
- 340acaa: Honor a non-root `deployment.base` in the dev server's `Accept: text/markdown` negotiation. The rewrite matched the base-prefixed request URL against the base-less content routes, so markdown negotiation silently did nothing under a configured `base`. The base is now stripped before matching and re-added to the rewritten `.md` URL.
|
|
459
|
+
- 22aa026: Truncate OG image titles by code point instead of UTF-16 unit. A long title that was cut mid-emoji could leave a lone surrogate — a broken glyph — right before the ellipsis. Truncation now slices whole characters.
|
|
460
|
+
- 637e935: Fix two package-manager conversions in ` ```package-install ` blocks. A global uninstall (`npm uninstall -g eslint`) produced the invalid `yarn remove -g eslint` for Yarn Classic; it now emits `yarn global remove eslint`, mirroring the global-add handling. And `npm ci` was rewritten as the nonsensical `yarn run ci` / `pnpm run ci`; it now maps to each manager's frozen-lockfile install (`pnpm install --frozen-lockfile`, etc.).
|
|
461
|
+
- af71d2a: Only collapse a trailing `index` segment when deriving a custom page's route. A folder literally named `index` (e.g. `pages/index/foo.astro`) previously lost its segment and mapped to `/foo` instead of `/index/foo`, because every `index` part was stripped rather than just the filename.
|
|
462
|
+
- 48b2d55: Validate `--port` on `blume dev` and `blume preview`. A non-numeric value (`--port abc`) became `NaN`, which then flowed into `http://localhost:NaN` as the dev server's `deployment.site` fallback — corrupting canonical URLs, OG image links, and the sitemap fallback. An invalid or out-of-range port now errors out instead.
|
|
463
|
+
- eb56673: Don't let one missing file abort a whole remote Markdown source. The `files` mode fetched every file in a single `Promise.all`, so a single 404 (a page renamed or deleted upstream) rejected the batch and failed a cache-less build with none of the healthy pages imported. Failed files are now skipped with a per-file warning and the rest import; a source only hard-fails when _every_ file fails (so it can still fall back to cache or surface a real outage).
|
|
464
|
+
- 28b95cc: Stop Sanity documents with non-ASCII slugs from overwriting each other. When a `slug.current` (or configured slug field) slugified to an empty string — e.g. a CJK slug — the entry fell back to a constant `untitled.md`, so multiple such documents collided on one ref and all but the last were silently dropped. The fallback now uses the document's unique `_id`, matching the Notion source.
|
|
465
|
+
- 8fb4105: Keep angle-bracket type parameters inside inline code in the search index. When reducing Markdown to searchable text, the HTML/JSX strip ran before inline code was unwrapped, so `` `Array<Item>` `` indexed as just `Array` — searches for `Item`, `Response`, `u8`, and the like silently missed. Inline-code contents are now preserved through the HTML strip, in both the on-page and MCP/Ask AI indexes.
|
|
466
|
+
- 0a2e7ef: Stop the Algolia and Typesense search syncs from leaving stale records behind. Both previously upserted keyed on the route, so a page deleted or renamed between builds stayed in the hosted index forever and surfaced as a search result that 404s. Algolia now uses `replaceAllObjects` (an atomic full replace) and Typesense drops and recreates its collection each sync, matching the Orama Cloud sync's snapshot-and-replace behavior.
|
|
467
|
+
- 94aaee1: Escape and URL-encode routes in `sitemap.xml`. A route containing an `&` (e.g. a content file named `Tips & Tricks.md`) previously emitted an unescaped `&` in `<loc>`, which is not well-formed XML — strict parsers and Google Search Console reject the entire sitemap. Routes are now percent-encoded and XML-escaped, sharing the same escaper as the RSS feed.
|
|
468
|
+
- 352fc90: Harden the generated **Ask AI** endpoint. `POST /api/ask` now validates the request body — a malformed or non-JSON body, or a `messages` value that isn't a 1–40 item array within a size cap, returns a `400` instead of throwing an unhandled `500`. The model call is wrapped so a streaming error returns a `500` rather than crashing the request. The message caps also bound how much a single call to this unauthenticated endpoint can spend against your model; the docs now recommend fronting it with a rate limiter.
|
|
469
|
+
- 5637599: `blume init` now ensures `.blume/` and `dist/` are git-ignored. It creates a `.gitignore` if the project doesn't have one, and appends only the missing entries (trailing-slash agnostic) when it does, so re-running is a no-op.
|
|
470
|
+
- 3754281: Retry Notion API calls on rate limits instead of aborting the import. A large workspace fans out many concurrent block-children requests, so a single `429` would reject the batch and fail the whole Notion source. Requests now retry with `Retry-After`-aware exponential backoff before giving up.
|
|
471
|
+
- 670415c: Make `blume add`'s import rewriting statement-aware. It previously rewrote any `from "./…"` substring, so a relative specifier appearing inside a string or JSX text in a component could be mangled. Rewriting is now anchored to actual `import`/`export` statements at the start of a line (multiline import bodies still handled), leaving in-string and in-JSX text alone.
|
|
472
|
+
- 97ddec1: Add `<lastmod>` to `sitemap.xml`. Pages that carry a modified date (from git or frontmatter) now emit a W3C-format `<lastmod>`, giving crawlers a recrawl signal; pages without a date are left as a plain `<url>`.
|
|
473
|
+
- def7cd4: Warn when a GitHub remote source hits the tree-listing limit. The git-trees API caps very large repos and sets `truncated: true`, which was ignored — so a big repo would silently enumerate only part of its files with no indication. Blume now emits a `BLUME_SOURCE_TRUNCATED` warning when that happens.
|
|
474
|
+
|
|
475
|
+
## 0.3.0
|
|
476
|
+
|
|
477
|
+
### Minor Changes
|
|
478
|
+
|
|
479
|
+
- 5115383: `blume build` gains deployment override flags — `--output static|server`, `--adapter vercel|node|netlify|cloudflare`, and `--base <path>` — that override the corresponding `blume.config.ts` deployment fields for one build (handy for CI matrices and previews). `--analyze` prints a client-JavaScript bundle report (each `_astro/*.js` chunk largest-first, plus the total) so you can catch weight regressions without extra tooling.
|
|
480
|
+
- 6f20875: Complete the **component override API**. `defineComponents` now supports:
|
|
481
|
+
|
|
482
|
+
- **An `islands` group** — register interactive framework components for use in every MDX page (the config-file equivalent of the `islands/` folder), hydrated by default (`client: "visible"`).
|
|
483
|
+
- **Hydration on overrides** — any `mdx` or `layout` override can take a descriptor `{ component, client, media }` and hydrate with a real Astro `client:*` directive (`load`/`idle`/`visible`/`media`/`only`).
|
|
484
|
+
- **Path-string references** — reference a component by path (`Footer: "./components/footer.astro"`) instead of importing it.
|
|
485
|
+
- **A friendly diagnostic** — Blume warns at build time when an override points to a React/Vue/Svelte component with no hydration mode (so it would silently render as dead static HTML).
|
|
486
|
+
|
|
487
|
+
Overrides are read by statically analyzing `components.ts` (never executing it), so Blume can emit the static imports and hydration wrappers Astro needs. Imported components still work as before; the new forms are additive.
|
|
488
|
+
|
|
489
|
+
- 968d449: Export per-component prop types from `blume/components`, so you can type an override or wrapper against the built-in's contract:
|
|
490
|
+
|
|
491
|
+
```tsx
|
|
492
|
+
import type { CalloutProps } from "blume/components";
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
Types are provided for the content components (`CalloutProps`, `CardProps`, `CardGroupProps`, `BadgeProps`, `TabsProps`, `TabProps`, `StepsProps`, `StepProps`, `AccordionProps`, `ColumnsProps`, `FrameProps`, `TooltipProps`, `IconProps`, and more). Each is derived from the component with Astro's `ComponentProps`, so it can never drift from the real props.
|
|
496
|
+
|
|
497
|
+
- a18b0e4: Static builds now emit platform redirect files so hosts issue real HTTP redirects instead of only Astro's client-side redirect pages: `_redirects` (Netlify, Cloudflare Pages), `vercel.json` (Vercel), and a structured `blume-redirects.json` manifest for manual wiring. A `_redirects`/`vercel.json` you ship in `public/` is preserved. Server/adapter builds are unchanged (the adapter handles redirects natively).
|
|
498
|
+
- e2f7d90: `blume dev` gains `--content-dir <dir>` (scan a different content folder without editing `blume.config.ts`, applied to the initial scan and every hot regenerate) and `--debug` (verbose Astro/Vite logging for troubleshooting).
|
|
499
|
+
- 7b8f026: Blume's own diagnostics (invalid config, frontmatter, or content errors) now show in the browser error overlay during `blume dev`, not just the terminal — each with its code, file/line, fix hint, and docs link. The overlay updates on every save and clears on the next successful reload.
|
|
500
|
+
- 316d862: Add `--json` to `blume validate` and `blume doctor`. With the flag, diagnostics are emitted as a JSON document on stdout — each with `code`, `severity`, `message`, root-relative `file`, `line`/`column`, and `docsUrl`, plus a severity summary — for CI pipelines and editor integrations. Human output is suppressed so stdout stays parseable.
|
|
501
|
+
- 5afd8dd: `blume init` gains starter and workflow flags:
|
|
502
|
+
|
|
503
|
+
- `--template docs|api|sdk|changelog` — scaffold from a starter (an OpenAPI reference, an SDK layout, or a changelog with a first entry) instead of the plain docs seed.
|
|
504
|
+
- `--package-manager npm|pnpm|yarn|bun` — tailor the printed next-steps.
|
|
505
|
+
- `--eject` — scaffold and immediately eject to a standalone Astro project, or (when dependencies aren't installed yet) guide you to `blume eject` after install.
|
|
506
|
+
|
|
507
|
+
- 624d797: Expose the full set of overridable **layout slots**. Alongside the existing `Header`, `Sidebar`, `Breadcrumbs`, `TableOfContents`, and `Pagination`, you can now replace `Layout` (the whole page shell), `Logo`, `Search`, `MobileNav`, and the three content-injection slots `PageHeader`, `PageFooter`, and `Footer` — the last three have no built-in and render nothing until you set them. Each override receives the same props as the built-in it replaces. Register them the same way as before:
|
|
508
|
+
|
|
509
|
+
```ts
|
|
510
|
+
import { defineComponents } from "blume";
|
|
511
|
+
import Footer from "./components/Footer.astro";
|
|
512
|
+
|
|
513
|
+
export default defineComponents({ layout: { Footer } });
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
- 40ed2b8: Render `navigation.selectors`. Configured selectors (Mintlify-style partition switchers — product, version, or any grouped destinations) now appear as zero-JS dropdowns in the header, highlighting the option that matches the current route. Each item supports a label, path, icon, description, and tag. Previously selectors validated and built into the graph but nothing displayed them.
|
|
517
|
+
- c94bcb9: Add performance-budget enforcement to `blume build`. `--budget-js <kb>` and `--budget-css <kb>` measure the total client `_astro/*.js` / `*.css` a build ships and fail (exit 1) when it exceeds the cap — turning a documented budget into a real CI gate. Pairs with `--analyze` (the per-file report).
|
|
518
|
+
- 2f1e33d: Prune the orphan `blume.config.ts` fields that validated but nothing read: `navbar`, `footer`, `icons`, `contextual`, and `styling` (Mintlify-compat leftovers). They no longer silently no-op — setting one is now a config error, so the surface reflects what Blume actually does. The Mintlify/Starlight migrators stop emitting them; per-partition `chromeVariants` keep only their `banner` override. (Site footers are available via the `Footer` layout slot, and code icons via `markdown.code.icons`.)
|
|
519
|
+
- 80cde3d: Add React island hooks, importable from `blume/hooks`:
|
|
520
|
+
|
|
521
|
+
- `useBlume()` — the site `config` + `navigation`.
|
|
522
|
+
- `usePage()` — the current page's `route` + `title`.
|
|
523
|
+
- `useSearch()` — query the configured search provider (`search`, `results`, `loading`); the provider client loads lazily on first use.
|
|
524
|
+
- `useAskAI()` — stream answers from the grounded Ask AI endpoint (`ask`, `messages`, `loading`, `reset`).
|
|
525
|
+
|
|
526
|
+
Islands hydrate independently, so `useBlume`/`usePage` read a compact JSON snapshot the layout serializes into the page (emitted only when the project ships React, so static sites pay nothing). Custom pages built with `PageLayout` opt in by passing a `clientData` prop.
|
|
527
|
+
|
|
528
|
+
- 16a7a15: Ship every built-in content component through `blume add`, not just the five layout slots. `blume add callout`, `card`, `card-group`, `code-group`, `badge`, `steps`, `step`, `tabs`, `tab`, `accordion`, `accordion-item`, `columns`, `column`, `frame`, `expandable`, `panel`, `tooltip`, `tile`, and `prompt` copy the component into your project as editable source (imports rewritten to `blume/*`), then print the `defineComponents({ mdx })` snippet to wire it back. The page `feedback` rating is also available (`blume add feedback`) via a new `Feedback` layout slot.
|
|
529
|
+
- 408d4ef: Add `blume/runtime` data helpers for custom pages. `getBlumeCollection(data, query?)` selects content routes from `blume:data` — filtered by collection, locale, or path prefix, with drafts/hidden pages excluded and sorted by path — so building a custom index or listing is a one-liner. The new `<BlumePage>` component (`blume/components/BlumePage.astro`) renders a content entry's body inside a custom page with Blume's built-in MDX components already wired in, with `components` and `collection` props for the rest. The runtime data types (`BlumeData`, `BlumeRoute`, …) are re-exported from `blume/runtime` too.
|
|
530
|
+
- 944d2aa: Add a `toc` option to `blume.config.ts`. `toc: false` hides the on-this-page table of contents site-wide; `toc: { minHeadingLevel, maxHeadingLevel }` changes which heading levels it lists (default: H2–H3). Previously the range was hardcoded and the TOC couldn't be turned off from config.
|
|
531
|
+
|
|
532
|
+
### Patch Changes
|
|
533
|
+
|
|
534
|
+
- 9159662: Ground **Ask AI** in your docs. The `/api/ask` endpoint now retrieves the most relevant pages for each question — via the same lexical Orama index that powers search — and injects them into the model's system prompt, so answers stay tied to your content and cite the pages they draw from instead of relying on the model's own knowledge. The in-page island also forwards the current page, which is added to the context first and used to scope retrieval to that page's locale. Grounding turns on automatically with Ask AI for the gateway, OpenRouter, and OpenAI-compatible backends; **Inkeep** is left untouched since it runs its own retrieval. No new configuration or dependencies.
|
|
535
|
+
- 6d03896: Add a `blume check` command that type-checks the docs site with `astro check`. It regenerates the `.blume` runtime, syncs Astro's content types, then runs the checker against the project — using the project-root `tsconfig.json` when present so authored `pages/` are covered, not just the generated project. Exits non-zero on type errors, so it slots into CI as a `typecheck` script.
|
|
536
|
+
- 40c9256: Diagnostics now carry a `docsUrl` pointing at the page that explains them. Every mapped error/warning (config, frontmatter, meta, sources, links, deployment, …) prints a `docs: https://useblume.dev/docs/…` line, so a failing build links straight to the fix.
|
|
537
|
+
- 037191b: Config and frontmatter validation errors now point at a line and column, not just the file. `diagnosticsFromZod` locates the offending key in the source text (narrowing key-by-key so a nested field lands under its parent), so a bad `blume.config.ts` field or a mistyped frontmatter value reports e.g. `at content/docs/guide.mdx:4:3`.
|
|
538
|
+
- c0c998b: Warn early when an enabled feature needs a runtime secret that isn't set, so it surfaces at `blume dev`/`build` instead of failing at the first request in production. Covers Ask AI (`AI_GATEWAY_API_KEY`, or the provider's `apiKeyEnv`) and Mixedbread search (`MIXEDBREAD_API_KEY`). It's a warning, not a hard failure, since the value may live only in the deploy environment.
|
|
539
|
+
- afafbc1: Add an integration **fixture matrix** (`test/fixtures.test.ts`) that exercises whole projects through the core pipeline — nested navigation, broken links, invalid frontmatter (with line/column), a custom `.astro` page, a React island, and static-vs-server feature gating — so the pieces keep working together, not just in isolation.
|
|
540
|
+
- d81aebc: Add a dev-only hydration-mismatch hint. When React reports an island hydration mismatch, Blume follows it with a friendly pointer explaining the usual causes (non-serializable props, non-deterministic render) and linking to the islands guide. It's guarded by `import.meta.env.DEV`, so it's tree-shaken out of production builds.
|
|
541
|
+
- 085ed4d: Unexpected (non-`BlumeError`) failures now print a stable internal-error report — a fixed `BLUME_INTERNAL` code, the message, a trimmed stack, and an environment dump (Blume/Node/platform) with a link to file an issue — instead of a bare stack trace. Wired into `prepare`, `validate`, and `doctor`, plus a top-level backstop for async failures that escape a command (e.g. in `blume dev`).
|
|
542
|
+
- 18fb645: Catch unknown MDX components with a friendly warning before the build hits Astro's cryptic "Expected component X to be defined" error. When an `.mdx` page uses a `<Tag>` that isn't a built-in, an island, or a `components.ts` override, Blume warns with the page it's on and how to fix it — `blume add <name>` when a registry item matches, otherwise how to register or add it. Code blocks, inline code, and quoted text are ignored to avoid false positives.
|
|
543
|
+
- 7ae1937: Blume now warns when a navigation icon name (in `blume.config.ts`, folder meta, or a page's `sidebar.icon`) isn't in its icon set — a typo used to just render nothing. Image paths, URLs, and inline SVG icons are left alone. Surfaced by `blume dev`, `blume build`, and `blume doctor`.
|
|
544
|
+
- 7a8cd85: Blume now catches common navigation mistakes that used to fail silently:
|
|
545
|
+
|
|
546
|
+
- **Missing target** — a tab/selector pointing at a route no page (content, custom `.astro`, or generated) serves.
|
|
547
|
+
- **Duplicate labels** — two sidebar entries sharing a title at the same level.
|
|
548
|
+
- **Hidden-in-sidebar** — a page marked `sidebar.hidden` that still appears in the sidebar (and therefore its prev/next pagination).
|
|
549
|
+
|
|
550
|
+
Surfaced by `blume dev`, `blume build`, and `blume doctor`.
|
|
551
|
+
|
|
552
|
+
- f583299: Support custom `og:image` overrides on custom pages. `PageLayout`'s `ogImage` prop now resolves a root-relative path (a file in `public/`) against `deployment.site` to the absolute URL crawlers require; absolute URLs pass through unchanged. This lets a marketing home or landing page set a bespoke social image instead of the generated Open Graph card.
|
|
553
|
+
- 307e156: Add a Playwright end-to-end harness for the docs site (a real Blume project, so it doubles as the framework's browser coverage). `playwright.config.ts` builds and previews the site, and `e2e/site.spec.ts` drives navigation, the sidebar, theme toggle, the mobile drawer, the search dialog, code-copy, tabs, and a custom page. Run with `bun run test:e2e` (after `bunx playwright install`).
|
|
554
|
+
- e18dcc8: Redesign the generated Open Graph card. It now uses a light layout with a brand lockup (the configured `logo` SVG, painted to the foreground, or an accent tile with the site initial as a fallback), the page title as a balanced headline, the site description as a muted subtitle, and a footer showing the repository slug and site host. Titles and descriptions use `text-wrap: balance`.
|
|
555
|
+
- e66583c: Error reports now relativize `.blume/` stack frames. A frame pointing into the hidden generated runtime is shortened from its machine-absolute path to a project-relative `.blume/…` path tagged `(generated)`, so internal-error stacks stay readable and the user-source frames (custom pages, island/override wrappers, which keep their real paths) stand out.
|
|
556
|
+
- d59a1b0: Add accessibility and visual-regression coverage to the Playwright suite. `e2e/a11y.spec.ts` runs axe-core (WCAG 2 A/AA) on the home, docs index, and a content page, checks the skip link is first in the tab order, verifies dark-mode color contrast, and renders under reduced motion. `e2e/visual.spec.ts` captures light/dark screenshot baselines for regression diffing.
|
|
557
|
+
|
|
558
|
+
## 0.2.0
|
|
559
|
+
|
|
560
|
+
### Minor Changes
|
|
561
|
+
|
|
562
|
+
- 7a30708: Add a built-in `github-releases` content source that turns a repository's GitHub Releases into `type: changelog` entries, so your release notes become your changelog with no files to maintain. The generated `/changelog` timeline now also reads staged (non-filesystem) sources, and the CLI loads `.env`/`.env.local` (cascading to the repo root) before the content scan so remote sources can read tokens like `GITHUB_TOKEN`. Because a changelog is supplementary, a fetch failure with no cache (e.g. a CI build without a token) degrades to an empty timeline with a warning instead of failing the build, and the `/changelog` page is still generated so its nav tab resolves.
|
|
563
|
+
|
|
564
|
+
## 0.1.5
|
|
565
|
+
|
|
566
|
+
### Patch Changes
|
|
567
|
+
|
|
568
|
+
- 6eb10b8: Hide tab-owned groups from the root sidebar. On a route under no tab (or the root `/` tab), the sidebar showed every top-level group — including the folders that already have their own header tab — so a section like Adapters or API appeared both as a tab and as a sidebar group. Those tab-owned groups are now dropped from the un-scoped sidebar, leaving only the pages that don't belong to a tab (and any group emptied by this is dropped too). If hiding them would blank the sidebar, the full tree is shown, so a route is never left empty.
|
|
569
|
+
|
|
570
|
+
## 0.1.4
|
|
571
|
+
|
|
572
|
+
### Patch Changes
|
|
573
|
+
|
|
574
|
+
- a41a9d7: Insulate the `<Component>` live preview from the page's prose styles. The preview renders inside the content's `.prose` wrapper, so Tailwind Typography bled into the previewed component (heading sizes, link colors, list markers, paragraph spacing), making it look unlike its real rendering. The Preview pane now carries `not-prose`; the Code pane keeps prose so the highlighted source stays styled.
|
|
575
|
+
- a1155c4: Add a default 404 page. Blume now generates a not-found page at Astro's reserved `src/pages/404.astro` path, so static builds ship a `dist/404.html` and `blume dev` serves it for unmatched routes — previously an unknown URL fell back to Astro's unstyled default. The page renders through `PageLayout` (header + search, no sidebar), is centered and `noindex`, and its copy comes from new translatable `notFound` UI strings (`title`, `description`, `home`), overridable per locale via `i18n.ui`. Drop a `pages/404.astro` to replace it entirely: Blume skips the default when the project already owns `/404` (a custom page or a `404.md` content page), so the override never collides. The same default is written on `blume eject`.
|
|
576
|
+
- 875eac0: Navigation tabs now scope the sidebar to their section. Previously `navigation.tabs` rendered as header links but every page still showed one global sidebar; the `sidebarVariants` data the model carried was never consumed at render time. Now, when the current route falls under a tab's `path`, the sidebar shows only that tab's section (the folder at that path) — so a multi-section site (e.g. Adapters / API / AI tabs) drills each tab into its own pages, the way Fumadocs' root folders do. It needs no extra config beyond the tabs: each group carries its URL path, and the renderer picks the section matching the route, falling back to the full sidebar when no tab matches. Breadcrumbs and pagination follow the scoped tree.
|
|
577
|
+
|
|
578
|
+
## 0.1.3
|
|
579
|
+
|
|
580
|
+
### Patch Changes
|
|
581
|
+
|
|
582
|
+
- 46f539c: Let `<Component>`'s `examples` config be a glob, not just a directory. When it contains glob magic (`*`, `?`, `[]`, `{}`, or `!`), only matching files are discovered and a `<Component path>` key is relative to the glob's static prefix. This lets a shadcn-style registry that colocates each component's source (named exports, no default) with its example (default export) be targeted directly — e.g. `examples: "registry/<pkg>/**/examples/*"` previews just the examples instead of sweeping in the sources and failing the build with `"default" is not exported`. Also makes `blume eject` honor the configured `examples` directory, which it previously ignored.
|
|
583
|
+
- 84ef03c: Stop the search preflight from falsely warning `Search provider "orama" needs "@orama/orama", which isn't installed` on a successful build. The check resolved the provider SDK from the project root only, so under isolated linkers (Bun's `isolated` mode, pnpm) a SDK Blume ships — Orama, the default provider — looked missing even though the index built fine via the `.blume` deps link. It now also resolves from Blume's own package (the same dependency set the build uses), so a shipped SDK is recognized; a genuinely uninstalled peer (Algolia, Typesense, …) still warns.
|
|
584
|
+
|
|
585
|
+
## 0.1.2
|
|
586
|
+
|
|
587
|
+
### Patch Changes
|
|
588
|
+
|
|
589
|
+
- b6a2506: Surface a clear, actionable diagnostic for the split-layout Astro conflict that a symlink can't repair. When a hoisted install pulls a second Astro to the project root (e.g. a dependency with a type-only `astro@6`) that shadows Blume's, and `@astrojs/mdx` is hoisted away from Blume's own Astro, `ensureDepsLink` can't reconcile the split with one symlink and leaves it for a root `overrides`/`resolutions` pin. Previously it did so silently, and the build later crashed deep in Astro on a missing export (e.g. `chunkToString`) with no hint at the cause. `blume dev`/`build` now warn up front — naming the conflicting versions and telling you to pin Blume's Astro with a package.json `overrides` (npm/bun/pnpm) or `resolutions` (yarn) entry — and the warning clears itself once the pin is in place.
|
|
590
|
+
- 40c7bd7: Make `<Component>`'s examples directory configurable. `<Component path>` previously only resolved live previews (and their source) from a top-level `examples/` directory, so projects whose examples live elsewhere — e.g. a registry layout like `registry/<pkg>/…`, which also doubles as the shadcn payload — couldn't adopt it. Set `examples` in `blume.config.ts` to point at any directory under the project root (default `"examples"`); a `<Component path>` key is then relative to that directory. For example, with `examples: "registry/files-sdk"`, a file at `registry/files-sdk/file-list/basic.tsx` is `<Component path="file-list/basic" />`.
|
|
591
|
+
- b6a2506: Fix `blume build` failing under isolated package-manager linkers (Bun's `isolated` mode, pnpm) with `Cannot find package 'zod'` (or `shiki`, `sharp`, `@takumi-rs/core`, …) during static page generation. Astro's static build emits a self-contained SSR bundle to `dist/.prerender/` and runs it to render the HTML; that bundle leaves Blume's render-time dependencies external, so Node resolves them by walking up from `dist/.prerender/`. The earlier dependency-link fix only repaired resolution rooted at `.blume/`, and `dist/` is a separate tree an isolated linker never hoists Blume's deps into, so prerendering died. Blume now drops the same `node_modules` symlink beside the prerender bundle (removed again with `dist/.prerender/` once generation finishes, so nothing leaks into your published output), and forces Blume's render-time deps external on both build environments so an isolated linker doesn't bundle a symlinked store copy and strand one of its own transitive dependencies (e.g. `batchwork` via `@astrojs/markdown-satteri`) as an unresolvable import.
|
|
592
|
+
|
|
593
|
+
## 0.1.1
|
|
594
|
+
|
|
595
|
+
### Patch Changes
|
|
596
|
+
|
|
597
|
+
- 52fdcb4: Auto-detect an Apple touch icon by filename, the way favicons already work. Drop an `apple-icon.png` (or `.jpg`/`.jpeg`, or `apple-touch-icon.png`) in your project root or `public/` directory and Blume wires up `<link rel="apple-touch-icon">` for you — no config required. A file in `public/` is referenced by URL (the reliable path for iOS); there's no default, so no tag is emitted when the project ships none.
|
|
598
|
+
- ac174bd: Document and type the `blume:data` module that custom pages import. Export `BlumeData` (and its parts — `BlumeDataConfig`, `BlumeRoute`, `BlumeFeed`, `BlumeLogo`, `BlumeFavicon`, `BlumeBanner`, `BlumeDataI18n`, `UIStrings`) from `blume`, so a custom `.astro` page can `import type { BlumeData } from "blume"` instead of reading the generator to learn the shape. The generated runtime now declares `blume:data` with that type, and `buildRuntimeData` is annotated with it so the exported type and the emitted JSON can't drift. The custom-pages guide's data table is expanded to the full surface — `config` (now listing favicon/appleIcon/banner/theme/site/repoUrl/search/i18n/mcp/og/analytics/...), plus `navigation`, `navigationByLocale`, `routes`, `feeds`, `fontCssVars`, `ui`, and `uiByLocale`.
|
|
599
|
+
- 2a3acb7: Add a `CodeBlock` component and a `highlightCode` helper for themed code outside the Markdown pipeline. There was no way to highlight a string with Blume's configured Shiki theme except by writing a fenced code block, so showing code on a landing page or inside a custom component meant pulling in raw Shiki and hand-writing a `[data-theme="dark"]` swap. `CodeBlock` (usable in any MDX page, or imported from `blume/components/content/CodeBlock.astro`) renders a `code` string with the same themes, transformers, and light/dark swap as fenced code — `<CodeBlock lang="ts" code={source} />`. The underlying `highlightCode(code, lang)` is exported from `blume/markdown` for rendering to an HTML string directly. The `<Component>` source view now shares the same helper.
|
|
600
|
+
- fe75624: Add `<Component>` — render an example file from your project's `examples/` directory as a live, hydrated preview alongside its highlighted source, in tabs. Point it at a file with `<Component path="forms/login" />` (the path under `examples/`, without the extension); React, Vue, Svelte, and Astro examples are all supported.
|
|
601
|
+
- fe75624: Add `<Diff>` — render a git-style diff with `@pierre/diffs`, highlighted with the same Shiki theme as your code blocks and produced entirely at build time (no client JavaScript). Accepts two inline strings (`old`/`new`), two file paths (`before`/`after`), or a unified patch (an inline `patch` string or a `src` file).
|
|
602
|
+
- 0a147fb: Fix the Fumadocs `meta.json` → sidebar migration for the common flat-files-plus-separators layout. The Extract operator (`...folder`) is no longer kept as a literal `"...folder"` page slug; it now keeps the folder's place in the ordering and renders as a normal group. `---Section---` separators, which were previously dropped with a warning, are rebuilt as route-transparent Blume group folders: a section's flat pages move into a `(Section)/` folder (with a `meta.ts` preserving their order), a section that is a single folder is left in place, and links are reported for manual navbar placement. Routes are unchanged and per-folder `meta.ts` keeps working, since the migration reshapes the filesystem rather than emitting a global `navigation.sidebar` override.
|
|
603
|
+
- 6501d73: Repair `blume dev`/`build` when a hoisted install resolves the _wrong_ Astro. Previously `ensureDepsLink` only relinked Blume's deps when Astro was unresolvable from `.blume/` (isolated linkers, pnpm); if a sibling workspace pinned an older major (e.g. `astro@6` for a type-only import) and the package manager hoisted it to the project root, `.blume/` resolved that shadowing copy, `@astrojs/mdx@7` bound to it, and the build crashed on a missing export. The link decision now compares _which_ Astro resolves — Blume's own versus a shadowing one — and links Blume's dependency directory in whenever they differ, not just when Astro is missing. This only happens when Blume's deps are a co-located, consistent set (Astro beside the `@astrojs/mdx` that binds to it); a split layout, where the integration is hoisted away from a conflicting Astro, can't be fixed by one symlink and still needs a root `overrides`/`resolutions` pin, so it's left untouched rather than half-fixed.
|
|
604
|
+
- 49be339: Fix `blume dev`/`build` failing to resolve Astro and its integrations under isolated package-manager linkers (Bun's `isolated` mode, pnpm), which forced projects to redeclare Blume's dependencies by hand. The generated `.blume/` runtime now locates Blume's real dependency directory — whether nested under the package or installed as siblings in a virtual store — and symlinks it in, so the generated config's bare specifiers resolve without the project adding any deps. Stale or broken `.blume/node_modules` links are also detected and rebuilt.
|
|
605
|
+
- 6a06d82: Finish the Fumadocs migration teardown so the project builds as Blume without manual cleanup. After moving content and writing the config, `blume migrate fumadocs` now repoints the `dev`/`build`/`start` scripts at the Blume CLI (`blume dev`/`build`/`preview`) and drops the `fumadocs-mdx` postinstall, adds `.blume/` and `dist/` to `.gitignore`, and prints a "safe to delete" checklist of the leftover Next/Fumadocs files it found (`next.config.*`, `source.config.*`, `mdx-components.tsx`, `app/`, …) plus a reminder to remove the `next` tsconfig plugin and the `.next`/`.source` ignore lines. It also derives a better site title for monorepos: a generic package name like `web` (from `apps/web`) now falls back to the repository's directory name. (The script-rewrite, gitignore, and leftover-checklist helpers live in the shared migration toolkit for other migrators to adopt.)
|
|
606
|
+
- e6914c0: Generate Open Graph cards for custom pages, including the home. OG images were generated per content route only, so a custom landing page at `/` — the most-shared URL — got no `/og/index.png` and had to ship a static `public/og.png`. Blume now renders a card for every static, public custom page (skipping dynamic `[param]` routes and private `_partial`/`.well-known` segments): the home uses the site title with the site description as its eyebrow, and a deeper page is titled from its last path segment. `PageLayout` derives the page's `canonical` and `og:image` from `siteUrl` + `ogEnabled` automatically (explicit `ogImage`/`canonical` still override), so a custom page wired from `blume:data` gets a themed card with no extra work.
|
|
607
|
+
- e22d957: Add `PageLayout` for landing, marketing, and other full-width pages. `RootLayout` hard-codes the docs 3-column grid (sidebar + prose + TOC), so building a custom page like a landing page meant hand-rolling the entire document shell — re-importing the header/favicon/fonts, copying the theme + banner pre-paint scripts, wiring `fontCssVars`, and rebuilding the banner markup. `PageLayout` (import from `blume/components/layout/PageLayout.astro`) provides that shell — `<head>`, theme, fonts, favicon, banner, and header — then a single full-width `<slot />` for the body, plus an optional `footer` slot rendered after `<main>`. Props come straight from `blume:data`. The two layouts now share the theme/banner pre-paint scripts so they can't drift, and the bundled docs landing page is built on `PageLayout`.
|
|
608
|
+
- 9434520: Ship compiled `.d.ts` declarations for the public API so you can type-check your own Blume project. Previously the `blume` and `blume/schema` exports pointed straight at `src/*.ts`, so the moment a consumer's `tsc`/`tsgo` touched a file importing `blume` (`blume.config.ts`, every `meta.ts`, `components.ts`) it followed into Blume's source and surfaced errors it couldn't resolve — `.ts` import extensions (TS5097), `node:fs`, and migrator internals — forcing you to exclude your own config from type-checking. The build now emits declarations to `dist/types/`, and the exports map resolves the `types` condition to them while the runtime still resolves to source. `defineConfig`/`defineMeta` now type-check and autocomplete in editors without the source leaking.
|
|
609
|
+
- 482bd71: Wire the project's tsconfig `paths` into the generated runtime's Vite aliases, so `@/`-style imports resolve in `blume dev`/`build`. The generated `.blume/` is its own Astro project with its own tsconfig and never inherited the project's, so shadcn-style imports like `@/lib/utils` in custom pages, islands, and components failed to resolve and had to be rewritten to relative paths. Blume now reads `compilerOptions.paths` (and `baseUrl`) from the project's `tsconfig.json`/`jsconfig.json` — tolerating JSONC and following a relative `extends` to the file that declares them — and emits each mapping as a `resolve.alias` entry (longest prefix first), so those components port over unchanged. Reading is best-effort: an unparseable or alias-less config simply yields no aliases.
|
|
610
|
+
- 83aab31: Fix `blume validate` false-flagging valid heading anchors. Heading anchor ids were derived for the manifest with a hand-rolled slugifier that collapsed consecutive dashes (`--` → `-`) and didn't disambiguate repeated headings, while the renderer assigns ids with `github-slugger`. So a link like `/api/copy#the-read--write-fallback` (matching the real rendered id) was reported broken, and a link to a repeated heading's `#setup-1` had no match. Heading extraction now uses the same per-document `github-slugger` as the renderer, so the manifest's anchor ids — and the on-page table-of-contents links built from them — match the rendered heading ids exactly. (`slugify` still handles content/route slugs.)
|
|
611
|
+
- f412250: `blume validate` now treats configured redirects as valid link targets. A content link to a path that only exists as a `redirects` entry (e.g. `/providers`, which redirects to `/providers/openai`) was flagged as a broken link, even though it resolves at runtime. Link validation now accepts any link whose target matches a configured `redirect.from`, removing the false positive.
|
|
612
|
+
- 5e35945: Fix `blume dev`/`build` crashing with "Function yaml.safeLoad is removed in js-yaml 4" when a workspace resolves js-yaml 4 for gray-matter. Front-matter parsing now routes through an explicit js-yaml `load`/`dump` engine instead of gray-matter's removed `safeLoad` default.
|
|
613
|
+
|
|
614
|
+
## 0.1.0
|
|
615
|
+
|
|
616
|
+
### Patch Changes
|
|
617
|
+
|
|
618
|
+
- 2aa1da0: First alpha release (v0.0.1) for testing.
|