blume 2.1.3 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +134 -0
- package/README.md +4 -4
- package/dist/cli/{chunk-y4msrwm9.js → chunk-080mfch6.js} +15 -15
- package/dist/cli/{chunk-gfc5fqvf.js → chunk-1ch3ct3r.js} +18 -18
- package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-1ch3ct3r.js.map} +1 -1
- package/dist/cli/{chunk-32khwcb6.js → chunk-2ssh60qh.js} +42 -69
- package/dist/cli/{chunk-32khwcb6.js.map → chunk-2ssh60qh.js.map} +9 -10
- package/dist/cli/{chunk-9qzgg6mj.js → chunk-34wap3ed.js} +3 -3
- package/dist/cli/{chunk-k3gr1nm9.js → chunk-40vk8kgf.js} +13 -16
- package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-40vk8kgf.js.map} +3 -3
- package/dist/cli/chunk-487b95qy.js +329 -0
- package/dist/cli/chunk-487b95qy.js.map +13 -0
- package/dist/cli/chunk-4zxh25hc.js +157 -0
- package/dist/cli/chunk-4zxh25hc.js.map +10 -0
- package/dist/cli/chunk-69rjf786.js +146 -0
- package/dist/cli/chunk-69rjf786.js.map +11 -0
- package/dist/cli/{chunk-dqhg54mr.js → chunk-9h8mh2tk.js} +3 -3
- package/dist/cli/{chunk-dqhg54mr.js.map → chunk-9h8mh2tk.js.map} +2 -2
- package/dist/cli/{chunk-bqxaqn5p.js → chunk-9jqmq5hv.js} +8 -8
- package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-9jqmq5hv.js.map} +1 -1
- package/dist/cli/{chunk-dv2z0rzf.js → chunk-aafhwx74.js} +38 -13
- package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-aafhwx74.js.map} +5 -4
- package/dist/cli/{chunk-desvm72z.js → chunk-b680sv30.js} +22 -26
- package/dist/cli/chunk-b680sv30.js.map +13 -0
- package/dist/cli/{chunk-0w6hs479.js → chunk-beb0z983.js} +30 -18
- package/dist/cli/chunk-beb0z983.js.map +10 -0
- package/dist/cli/{chunk-1f882900.js → chunk-c5bjxq8v.js} +2 -2
- package/dist/cli/chunk-e1n41w9m.js +155 -0
- package/dist/cli/chunk-e1n41w9m.js.map +11 -0
- package/dist/cli/{chunk-sc93apfs.js → chunk-etckvbrh.js} +17 -17
- package/dist/cli/{chunk-sc93apfs.js.map → chunk-etckvbrh.js.map} +2 -2
- package/dist/cli/{chunk-bxwhtvw8.js → chunk-f260jdrn.js} +5 -5
- package/dist/cli/{chunk-74wfhv79.js → chunk-fnxgtjeq.js} +1 -1
- package/dist/cli/{chunk-ms9z66nz.js → chunk-gwy55cx3.js} +2 -2
- package/dist/cli/{chunk-ms9z66nz.js.map → chunk-gwy55cx3.js.map} +2 -2
- package/dist/cli/{chunk-dhwtqnnd.js → chunk-gxhcf2hs.js} +2 -2
- package/dist/cli/{chunk-tfycddbt.js → chunk-h0qwdbem.js} +2 -2
- package/dist/cli/{chunk-nbyvgnnm.js → chunk-hktq4j5r.js} +109 -49
- package/dist/cli/chunk-hktq4j5r.js.map +36 -0
- package/dist/cli/{chunk-twy7psdz.js → chunk-hn3g2b89.js} +14 -10
- package/dist/cli/chunk-hn3g2b89.js.map +10 -0
- package/dist/cli/{chunk-j1x92mx9.js → chunk-j4nfgn2j.js} +1 -1
- package/dist/cli/{chunk-dpy8qdjf.js → chunk-k45sq16q.js} +74 -183
- package/dist/cli/chunk-k45sq16q.js.map +18 -0
- package/dist/cli/{chunk-5cmts6dv.js → chunk-kmswjxj9.js} +7 -7
- package/dist/cli/{chunk-5cmts6dv.js.map → chunk-kmswjxj9.js.map} +1 -1
- package/dist/cli/{chunk-36bxs9c7.js → chunk-nqna8dzp.js} +27 -23
- package/dist/cli/chunk-nqna8dzp.js.map +10 -0
- package/dist/cli/{chunk-a57yh0h9.js → chunk-p834rkcn.js} +7 -7
- package/dist/cli/{chunk-a57yh0h9.js.map → chunk-p834rkcn.js.map} +1 -1
- package/dist/cli/{chunk-60hz265r.js → chunk-ppa6mg4d.js} +24 -11
- package/dist/cli/chunk-ppa6mg4d.js.map +10 -0
- package/dist/cli/{chunk-s0bdnc7v.js → chunk-q1wwrxzw.js} +5 -4
- package/dist/cli/chunk-q1wwrxzw.js.map +10 -0
- package/dist/cli/{chunk-ave1wcbr.js → chunk-qcyxkj44.js} +1 -1
- package/dist/cli/{chunk-124fvmzq.js → chunk-r5nm9w0c.js} +11183 -8806
- package/dist/cli/{chunk-124fvmzq.js.map → chunk-r5nm9w0c.js.map} +82 -66
- package/dist/cli/{chunk-ckrcm08h.js → chunk-rtvgmg2j.js} +48 -62
- package/dist/cli/{chunk-ckrcm08h.js.map → chunk-rtvgmg2j.js.map} +4 -5
- package/dist/cli/{chunk-297ajdcv.js → chunk-t2h8pwy1.js} +6 -6
- package/dist/cli/{chunk-297ajdcv.js.map → chunk-t2h8pwy1.js.map} +3 -3
- package/dist/cli/{chunk-gxtg6ed2.js → chunk-x60e15st.js} +21 -21
- package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-x60e15st.js.map} +3 -3
- package/dist/cli/{chunk-58bt3hag.js → chunk-x7bh6d9j.js} +4 -4
- package/dist/cli/{chunk-hvcxng5f.js → chunk-ydqzkhjn.js} +6 -6
- package/dist/cli/{chunk-kdpzw38a.js → chunk-yg8ckc3g.js} +95 -7
- package/dist/cli/chunk-yg8ckc3g.js.map +11 -0
- package/dist/cli/{chunk-0pmb4tr4.js → chunk-zxd5jrgx.js} +1205 -222
- package/dist/cli/chunk-zxd5jrgx.js.map +44 -0
- package/dist/cli/index.js +78 -42
- package/dist/cli/index.js.map +7 -6
- package/dist/types/ai/changelog-components.d.ts +18 -0
- package/dist/types/ai/changelog-markdown.d.ts +12 -0
- package/dist/types/ai/openapi-components.d.ts +7 -7
- package/dist/types/ai/operation-details.d.ts +39 -0
- package/dist/types/ai/relative-links.d.ts +3 -1
- package/dist/types/ai/serializers.d.ts +6 -4
- package/dist/types/analytics/head.d.ts +4 -2
- package/dist/types/analytics/script.d.ts +8 -2
- package/dist/types/components/content/youtube.d.ts +20 -0
- package/dist/types/components/layout/nav-utils.d.ts +8 -0
- package/dist/types/components/openapi/example-panels.d.ts +33 -0
- package/dist/types/components/openapi/helpers.d.ts +53 -11
- package/dist/types/components/openapi/snippets.d.ts +7 -1
- package/dist/types/core/alert-diagnostics.d.ts +10 -0
- package/dist/types/core/builtin-tags.d.ts +16 -0
- package/dist/types/core/changelog-list.d.ts +48 -0
- package/dist/types/core/closest-match.d.ts +6 -0
- package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
- package/dist/types/core/code-fences.d.ts +8 -1
- package/dist/types/core/config-input.d.ts +38 -6
- package/dist/types/core/content-assets.d.ts +16 -18
- package/dist/types/core/data.d.ts +6 -2
- package/dist/types/core/diagnostics.d.ts +14 -0
- package/dist/types/core/directive-diagnostics.d.ts +22 -8
- package/dist/types/core/former-routes.d.ts +14 -0
- package/dist/types/core/github.d.ts +5 -4
- package/dist/types/core/heading-markers.d.ts +65 -2
- package/dist/types/core/hidden-pages.d.ts +3 -0
- package/dist/types/core/includes.d.ts +23 -0
- package/dist/types/core/last-modified.d.ts +18 -6
- package/dist/types/core/links.d.ts +42 -2
- package/dist/types/core/load-module.d.ts +19 -4
- package/dist/types/core/manifest.d.ts +14 -1
- package/dist/types/core/markdown-mirrors.d.ts +22 -0
- package/dist/types/core/mcp-clients.d.ts +47 -0
- package/dist/types/core/mdx-elements.d.ts +32 -0
- package/dist/types/core/mdx-syntax.d.ts +100 -0
- package/dist/types/core/meta-diagnostics.d.ts +7 -0
- package/dist/types/core/meta.d.ts +32 -5
- package/dist/types/core/nav-diagnostics.d.ts +16 -2
- package/dist/types/core/navigation.d.ts +13 -0
- package/dist/types/core/ordering-prefix.d.ts +6 -0
- package/dist/types/core/pinned-ids.d.ts +23 -0
- package/dist/types/core/project-graph.d.ts +9 -1
- package/dist/types/core/redirect-patterns.d.ts +18 -0
- package/dist/types/core/relative-files.d.ts +31 -0
- package/dist/types/core/schema.d.ts +322 -11
- package/dist/types/core/sources/normalize.d.ts +101 -9
- package/dist/types/core/sources/types.d.ts +16 -0
- package/dist/types/core/static-files.d.ts +10 -0
- package/dist/types/core/static-host.d.ts +42 -0
- package/dist/types/core/svg-images.d.ts +26 -0
- package/dist/types/core/syntax-diagnostics.d.ts +14 -0
- package/dist/types/core/types.d.ts +42 -1
- package/dist/types/deploy/generated-files.d.ts +41 -0
- package/dist/types/deploy/redirects.d.ts +21 -7
- package/dist/types/markdown/code-title.d.ts +9 -5
- package/dist/types/markdown/directives.d.ts +8 -0
- package/dist/types/markdown/fence-language.d.ts +51 -0
- package/dist/types/markdown/fence-meta.d.ts +5 -0
- package/dist/types/markdown/github-alerts.d.ts +35 -0
- package/dist/types/openapi/asyncapi.d.ts +6 -5
- package/dist/types/openapi/checks.d.ts +10 -5
- package/dist/types/openapi/model.d.ts +55 -8
- package/dist/types/openapi/parse.d.ts +4 -1
- package/dist/types/ratelimit/index.d.ts +2 -0
- package/dist/types/ratelimit/memory.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +40 -0
- package/dist/types/ratelimit/unkey.d.ts +48 -0
- package/dist/types/sources/filesystem.d.ts +14 -4
- package/dist/types/sources/mdx-remote.d.ts +6 -3
- package/dist/types/sources/registry.d.ts +3 -3
- package/dist/types/theme/color.d.ts +33 -0
- package/dist/types/theme/palette.d.ts +122 -0
- package/docs/01-quickstart.mdx +1 -1
- package/docs/02-deployment.mdx +24 -8
- package/docs/04-migrating.mdx +16 -4
- package/docs/advanced/changelog.mdx +27 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +1 -1
- package/docs/cli/index.mdx +4 -2
- package/docs/cli/validate.mdx +10 -7
- package/docs/configuration/analytics.mdx +2 -0
- package/docs/configuration/customization.mdx +3 -1
- package/docs/configuration/index.mdx +7 -6
- package/docs/configuration/rate-limiting.mdx +20 -1
- package/docs/configuration/theming.mdx +5 -1
- package/docs/content/components.mdx +26 -6
- package/docs/content/frontmatter.mdx +1 -1
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/includes.mdx +6 -2
- package/docs/content/index.mdx +11 -1
- package/docs/content/islands.mdx +2 -0
- package/docs/content/meta.mdx +9 -3
- package/docs/content/navigation.mdx +14 -6
- package/docs/content/sources/obsidian.mdx +1 -1
- package/docs/content/sources/remote-mdx.mdx +3 -1
- package/docs/content/syntax.mdx +76 -8
- package/docs/content/variables.mdx +3 -1
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/json-api.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/mcp.mdx +40 -8
- package/docs/discoverability/open-graph.mdx +1 -1
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/graphql.mdx +2 -0
- package/docs/references/openapi.mdx +45 -7
- package/package.json +4 -4
- package/skills/blume/SKILL.md +2 -2
- package/skills/blume-migrate/SKILL.md +51 -29
- package/skills/blume-migrate/references/docsify.md +262 -0
- package/skills/blume-migrate/references/docus.md +298 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -5
- package/skills/blume-migrate/references/fern.md +327 -0
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/gitbook.md +267 -0
- package/skills/blume-migrate/references/github-wiki.md +259 -0
- package/skills/blume-migrate/references/jekyll.md +253 -0
- package/skills/blume-migrate/references/mdbook.md +256 -0
- package/skills/blume-migrate/references/mintlify.md +5 -5
- package/skills/blume-migrate/references/mkdocs.md +236 -0
- package/skills/blume-migrate/references/monorepo.md +20 -8
- package/skills/blume-migrate/references/nextra.md +5 -5
- package/skills/blume-migrate/references/readme.md +257 -0
- package/skills/blume-migrate/references/redocly.md +198 -0
- package/skills/blume-migrate/references/starlight.md +3 -3
- package/skills/blume-migrate/references/vitepress.md +204 -0
- package/skills/blume-migrate/references/vuepress.md +271 -0
- package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
- package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
- package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
- package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
- package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
- package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
- package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
- package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
- package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
- package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
- package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
- package/src/ai/changelog-components.ts +24 -0
- package/src/ai/changelog-markdown.ts +45 -41
- package/src/ai/component-markdown.ts +22 -9
- package/src/ai/llms.ts +36 -5
- package/src/ai/markdown.ts +2 -2
- package/src/ai/openapi-components.ts +25 -9
- package/src/ai/operation-details.ts +208 -0
- package/src/ai/relative-links.ts +48 -8
- package/src/ai/serializers.ts +7 -6
- package/src/ai/site-skill.ts +6 -2
- package/src/analytics/head.ts +11 -5
- package/src/analytics/script.ts +13 -3
- package/src/astro/generate.ts +47 -11
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +27 -1
- package/src/astro/mdx-source-errors.ts +46 -0
- package/src/astro/templates.ts +93 -189
- package/src/audit/checks/redirects.ts +5 -1
- package/src/audit/redirects.ts +36 -19
- package/src/audit/report.ts +22 -9
- package/src/audit/run.ts +12 -28
- package/src/audit/terms.ts +23 -0
- package/src/audit/url.ts +2 -2
- package/src/cli/build-failure.ts +256 -7
- package/src/cli/command-meta.ts +1 -1
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/build.ts +12 -3
- package/src/cli/commands/check.ts +13 -2
- package/src/cli/commands/dev.ts +1 -1
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/init.ts +3 -3
- package/src/cli/commands/preview.ts +17 -1
- package/src/cli/commands/validate.ts +22 -10
- package/src/cli/prepare.ts +1 -1
- package/src/cli/preview-pages.ts +161 -0
- package/src/cli/required-secrets.ts +0 -1
- package/src/cli/unknown-flags.ts +1 -42
- package/src/components/code-copy.ts +51 -0
- package/src/components/code-language.ts +75 -0
- package/src/components/content/AccordionItem.astro +16 -1
- package/src/components/content/Callout.astro +11 -1
- package/src/components/content/Changelog.astro +189 -0
- package/src/components/content/CodeBlock.astro +8 -11
- package/src/components/content/Tabs.astro +16 -2
- package/src/components/content/YouTube.astro +6 -4
- package/src/components/content/code-block.ts +33 -0
- package/src/components/content/content-strings.ts +5 -1
- package/src/components/content/inline-markdown.ts +35 -8
- package/src/components/content/youtube.ts +49 -7
- package/src/components/layout/Analytics.astro +5 -1
- package/src/components/layout/NavTree.astro +8 -3
- package/src/components/layout/PageActions.astro +81 -23
- package/src/components/layout/RootLayout.astro +35 -32
- package/src/components/layout/SiteFooter.astro +31 -8
- package/src/components/layout/nav-utils.ts +14 -0
- package/src/components/layout/search/pagefind.ts +2 -1
- package/src/components/openapi/Operation.astro +4 -0
- package/src/components/openapi/PanelTabs.astro +9 -3
- package/src/components/openapi/RequestBody.astro +42 -8
- package/src/components/openapi/RequestPanel.astro +34 -53
- package/src/components/openapi/example-panels.ts +110 -0
- package/src/components/openapi/helpers.ts +195 -20
- package/src/components/openapi/operation-model.ts +63 -26
- package/src/components/openapi/request.ts +13 -0
- package/src/components/openapi/snippets.ts +14 -2
- package/src/core/alert-diagnostics.ts +89 -0
- package/src/core/builtin-tags.ts +76 -0
- package/src/core/changelog-list.ts +87 -0
- package/src/core/closest-match.ts +41 -0
- package/src/core/code-fence-diagnostics.ts +267 -0
- package/src/core/code-fences.ts +43 -7
- package/src/core/component-diagnostics.ts +65 -12
- package/src/core/config-input.ts +39 -5
- package/src/core/config.ts +46 -1
- package/src/core/content-assets.ts +64 -144
- package/src/core/data.ts +10 -3
- package/src/core/diagnostics.ts +36 -3
- package/src/core/directive-diagnostics.ts +265 -47
- package/src/core/former-routes.ts +46 -0
- package/src/core/git-ignored.ts +53 -0
- package/src/core/github.ts +5 -4
- package/src/core/heading-markers.ts +156 -2
- package/src/core/hidden-pages.ts +64 -0
- package/src/core/includes.ts +181 -41
- package/src/core/last-modified.ts +47 -10
- package/src/core/links.ts +438 -83
- package/src/core/load-module.ts +98 -9
- package/src/core/manifest.ts +12 -9
- package/src/core/markdown-mirrors.ts +52 -0
- package/src/core/mcp-clients.ts +87 -0
- package/src/core/mdx-elements.ts +153 -0
- package/src/core/mdx-syntax.ts +377 -0
- package/src/core/meta-diagnostics.ts +134 -0
- package/src/core/meta.ts +154 -55
- package/src/core/nav-diagnostics.ts +41 -4
- package/src/core/navigation.ts +70 -10
- package/src/core/ordering-prefix.ts +22 -2
- package/src/core/pinned-ids.ts +141 -0
- package/src/core/project-graph.ts +221 -29
- package/src/core/redirect-patterns.ts +41 -0
- package/src/core/relative-files.ts +145 -0
- package/src/core/schema.ts +110 -6
- package/src/core/sources/mdx-remote.ts +75 -14
- package/src/core/sources/normalize.ts +885 -179
- package/src/core/sources/notion.ts +5 -4
- package/src/core/sources/obsidian.ts +2 -5
- package/src/core/sources/types.ts +17 -0
- package/src/core/static-files.ts +40 -0
- package/src/core/static-host.ts +125 -0
- package/src/core/svg-images.ts +98 -0
- package/src/core/syntax-diagnostics.ts +491 -0
- package/src/core/types.ts +43 -1
- package/src/deploy/artifacts.ts +2 -28
- package/src/deploy/generated-files.ts +128 -0
- package/src/deploy/platforms/vercel.ts +25 -1
- package/src/deploy/redirects.ts +43 -16
- package/src/deploy/sitemap.ts +2 -1
- package/src/markdown/base-links.ts +87 -6
- package/src/markdown/code-title.ts +29 -13
- package/src/markdown/content-assets.ts +210 -0
- package/src/markdown/directives.ts +69 -5
- package/src/markdown/fence-language.ts +106 -0
- package/src/markdown/fence-meta.ts +42 -0
- package/src/markdown/github-alerts.ts +172 -0
- package/src/markdown/heading-anchors.ts +265 -56
- package/src/markdown/include.ts +30 -3
- package/src/markdown/index.ts +145 -40
- package/src/markdown/prompt-text.ts +95 -0
- package/src/markdown/relative-links.ts +37 -2
- package/src/markdown/route-snapshot.ts +22 -12
- package/src/markdown/svg-fallback.ts +51 -0
- package/src/markdown/title-heading.ts +134 -0
- package/src/migrate/migrate.ts +127 -2
- package/src/og/card.ts +14 -4
- package/src/openapi/asyncapi.ts +14 -6
- package/src/openapi/checks.ts +160 -15
- package/src/openapi/model.ts +172 -33
- package/src/openapi/parse.ts +13 -4
- package/src/openapi/render-mdx.ts +55 -9
- package/src/openapi/source.ts +87 -6
- package/src/ratelimit/index.ts +2 -0
- package/src/ratelimit/memory.ts +1 -1
- package/src/ratelimit/runtime.ts +81 -0
- package/src/ratelimit/schema.ts +2 -0
- package/src/ratelimit/unkey.ts +61 -0
- package/src/registry/eject.ts +0 -1
- package/src/registry/registry.ts +1 -1
- package/src/search/documents.ts +10 -2
- package/src/sources/filesystem.ts +28 -3
- package/src/sources/mdx-remote.ts +7 -15
- package/src/theme/color.ts +14 -0
- package/src/theme/entry.ts +22 -1
- package/src/theme/palette.ts +74 -1
- package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
- package/dist/cli/chunk-0w6hs479.js.map +0 -10
- package/dist/cli/chunk-150jk7km.js +0 -52
- package/dist/cli/chunk-150jk7km.js.map +0 -10
- package/dist/cli/chunk-36bxs9c7.js.map +0 -10
- package/dist/cli/chunk-53jqw8z0.js +0 -89
- package/dist/cli/chunk-53jqw8z0.js.map +0 -10
- package/dist/cli/chunk-60hz265r.js.map +0 -10
- package/dist/cli/chunk-desvm72z.js.map +0 -14
- package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
- package/dist/cli/chunk-es8h0v3j.js +0 -441
- package/dist/cli/chunk-es8h0v3j.js.map +0 -11
- package/dist/cli/chunk-kdpzw38a.js.map +0 -11
- package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
- package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
- package/dist/cli/chunk-twy7psdz.js.map +0 -10
- package/dist/cli/chunk-ydp3065p.js +0 -64
- package/dist/cli/chunk-ydp3065p.js.map +0 -10
- /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-080mfch6.js.map} +0 -0
- /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-34wap3ed.js.map} +0 -0
- /package/dist/cli/{chunk-1f882900.js.map → chunk-c5bjxq8v.js.map} +0 -0
- /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-f260jdrn.js.map} +0 -0
- /package/dist/cli/{chunk-74wfhv79.js.map → chunk-fnxgtjeq.js.map} +0 -0
- /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-gxhcf2hs.js.map} +0 -0
- /package/dist/cli/{chunk-tfycddbt.js.map → chunk-h0qwdbem.js.map} +0 -0
- /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-j4nfgn2j.js.map} +0 -0
- /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-qcyxkj44.js.map} +0 -0
- /package/dist/cli/{chunk-58bt3hag.js.map → chunk-x7bh6d9j.js.map} +0 -0
- /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-ydqzkhjn.js.map} +0 -0
|
@@ -73,7 +73,33 @@ changelog: {
|
|
|
73
73
|
|
|
74
74
|
Each takes a map of locale code to text too, like a [header tab label](/docs/content/i18n#per-locale-navigation). The index renders in the default locale, so it shows that locale's entry. Leave either unset and it keeps the built-in text, which a [UI string override](/docs/content/i18n#translated-ui) (`changelog.title` and `changelog.description` under `i18n.ui`) replaces.
|
|
75
75
|
|
|
76
|
-
The page appears only when nothing already occupies the `/changelog` route.
|
|
76
|
+
The page appears only when nothing already occupies the `/changelog` route.
|
|
77
|
+
|
|
78
|
+
### Writing your own index
|
|
79
|
+
|
|
80
|
+
To put something above the list — an introduction, a link to the feed, a note about your release cadence — write the page yourself and place `<Changelog />` where the list belongs. Blume still owns the list, so you only write the parts it has no slot for:
|
|
81
|
+
|
|
82
|
+
```mdx changelog/index.mdx
|
|
83
|
+
---
|
|
84
|
+
title: Changelog
|
|
85
|
+
description: Every Acme SDK release, newest first.
|
|
86
|
+
mode: center
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
Every release, newest first. Subscribe to the [RSS feed](/changelog/rss.xml) to follow along.
|
|
90
|
+
|
|
91
|
+
<Changelog />
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
A content page at `/changelog` takes over the route, so the generated page steps aside and yours renders instead. Put it at `changelog/index.mdx`, beside your entries, so the sidebar's Changelog group links to it — a `changelog.mdx` next to the folder adds a second Changelog item to the sidebar. [`mode: center`](/docs/content/frontmatter#layout) gives it the generated page's layout — no sidebar, no table of contents, a wider centered column — and the generated page renders the same component, so the two can't drift apart. The list downlevels to Markdown on the agent surfaces (`/changelog.md`, llms-full.txt, MCP `get_page`, search) exactly as the generated page's does.
|
|
95
|
+
|
|
96
|
+
The list is always the default locale's entries, wherever the tag sits — the rule every surface that publishes it already follows, so a translated page lists the same releases rather than disagreeing about which exist. Its dates read in the page's own language.
|
|
97
|
+
|
|
98
|
+
### Replacing the page entirely
|
|
99
|
+
|
|
100
|
+
For a design the component can't express, add a [custom page](/docs/advanced/custom-pages) at `pages/changelog.astro` — it takes over and Blume stops generating the default index. The `<Update>` component the previous timeline was built from still ships for a custom page that wants inline release notes. It isn't one of the MDX components, so import it in the `.astro` page itself: `import Update from "blume/components/content/Update.astro";`.
|
|
101
|
+
|
|
102
|
+
Building the list yourself means reproducing what `<Changelog />` does, including one thing that fails quietly: entries from a non-filesystem source (such as [GitHub Releases](#from-github-releases)) render through a parallel `staged` collection, so a page that reads `getCollection("docs")` alone lists none of them, with no warning. Prefer `<Changelog />` in a content page unless you genuinely need different markup.
|
|
77
103
|
|
|
78
104
|
## From GitHub Releases
|
|
79
105
|
|
package/docs/advanced/skills.mdx
CHANGED
|
@@ -15,7 +15,7 @@ npx skills add haydenbleasel/blume
|
|
|
15
15
|
|
|
16
16
|
## Migration
|
|
17
17
|
|
|
18
|
-
`blume-migrate` moves an existing docs site to Blume
|
|
18
|
+
`blume-migrate` moves an existing docs site to Blume from Mintlify, Docusaurus, GitBook, MkDocs, ReadMe, the [other named sources](/docs/migrating#sources), or any other framework. It targets idiomatic Blume rather than a line-by-line port, with a mapping reference for each named framework, a redirect for every URL that moves, and a report of anything it drops. The quickest way to run it is [`blume migrate`](/docs/migrating), which detects your framework and opens Codex or Claude Code on the copy bundled in the package. To use it from another agent, install it:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
npx skills add haydenbleasel/blume --skill blume-migrate
|
package/docs/cli/audit.mdx
CHANGED
|
@@ -28,7 +28,7 @@ Findings are grouped by check rather than listed per page, so the report reads a
|
|
|
28
28
|
- `--url <origin>` — also probe a live deployment for status codes, response headers, and configured redirects.
|
|
29
29
|
- `--external` — probe outbound links over the network.
|
|
30
30
|
- `--ignore <glob>` — with `--external`, don't probe an outbound link whose URL matches the glob, like `--ignore "https://api.acme.example/**"`. Repeat the flag for more patterns. It matches the way [`blume validate --ignore`](/docs/cli/validate#flags) does, and internal links are always checked.
|
|
31
|
-
- `--only <check|category>` / `--skip <check|category>` — narrow the report to, or away from, these checks or categories (comma-separated). A term that names no check or category is an error that suggests the closest one, so a typo can't quietly empty the report.
|
|
31
|
+
- `--only <check|category>` / `--skip <check|category>` — narrow the report to, or away from, these checks or categories (comma-separated). The audit count in the summary counts only the checks left in. A term that names no check or category is an error that suggests the closest one, so a typo can't quietly empty the report.
|
|
32
32
|
- `--list-checks` — print every check the audit can report, then exit.
|
|
33
33
|
- `--verbose` — list every affected page with each finding's full detail, instead of the first few.
|
|
34
34
|
- `--json` — emit the report as JSON on stdout.
|
package/docs/cli/doctor.mdx
CHANGED
|
@@ -15,8 +15,8 @@ blume doctor
|
|
|
15
15
|
|
|
16
16
|
- **The Node version** against the range the installed `blume` package supports, read from its own `engines` field. A version outside it is a warning: things may work, but it isn't a combination Blume tests.
|
|
17
17
|
- **`blume.config.ts`**, with the same validation a build runs. A removed or renamed key fails with a hint naming its replacement rather than a bare "unrecognized key".
|
|
18
|
-
- **Every content page and folder meta**: the diagnostics `blume dev` and `blume build` print as they load the project — invalid frontmatter, navigation problems, missing include targets, and the rest — collected in one report.
|
|
19
|
-
- **Navigation that leads nowhere**: a tab, selector item, featured link, header action, or call to action whose path matches no page, custom `.astro` page, generated route, or
|
|
18
|
+
- **Every content page and folder meta**: the diagnostics `blume dev` and `blume build` print as they load the project — invalid frontmatter, `.mdx` that doesn't [parse](/docs/content#markdown-and-mdx), navigation problems, missing include targets, and the rest — collected in one report.
|
|
19
|
+
- **Navigation that leads nowhere**: a tab, selector item, featured link, header action, or call to action whose path matches no page, custom `.astro` page, generated route, reference, `public/` file, or file Blume generates: a warning (`BLUME_NAV_MISSING_PAGE`), the same one `blume dev` and `blume build` print. A tab is checked where it links: its `href` when it has one, else its `path`.
|
|
20
20
|
- **[`<Component>`](/docs/content/components#component) examples that don't exist**: a `path` that names no file under `examples`, which the page would show as a "No example found" box: a warning (`BLUME_EXAMPLE_NOT_FOUND`) at its line, as `blume dev` and `blume build` print it. A `components.ts` override or island named `Component` replaces the built-in, and isn't checked.
|
|
21
21
|
- **Features that need a server** on a site configured for static output — the assistant, the MCP server, the Try it playground's built-in proxy, or server-mode search (Mixedbread): an error naming the feature, with the deployment adapter to switch to (or, when a host adapter is set to `output: "static"`, telling you to drop that option).
|
|
22
22
|
- **Packages your config needs** that aren't installed — the SDK a search, content source, assistant, or narration adapter imports, a deployment adapter's `@astrojs/*` package, or the renderer for Vue or Svelte islands: an error naming each package, with the install command for your package manager. `blume build` stops on the same check.
|
package/docs/cli/evals.mdx
CHANGED
package/docs/cli/index.mdx
CHANGED
|
@@ -26,7 +26,7 @@ blume <command> [options]
|
|
|
26
26
|
| [`blume translate`](/docs/cli/translate) | Translate docs into the configured locales with a local agent CLI. |
|
|
27
27
|
| [`blume version [id]`](/docs/cli/version) | Freeze the current docs as an archived version (no id lists configured versions). |
|
|
28
28
|
| [`blume skill`](/docs/discoverability/agent-discovery#your-sites-skill) | Write your docs' agent skill with Codex or Claude Code, in place of the generated one. |
|
|
29
|
-
| [`blume migrate [source]`](/docs/migrating) | Move a Mintlify,
|
|
29
|
+
| [`blume migrate [source]`](/docs/migrating) | Move a Mintlify, Docusaurus, GitBook, MkDocs, ReadMe, or other docs site to Blume with Codex or Claude Code. |
|
|
30
30
|
| [`blume upgrade`](/docs/upgrading) | Move to a new major: bump `blume`, then list the config changes left or hand them to Codex or Claude Code. |
|
|
31
31
|
|
|
32
32
|
## Common flags
|
|
@@ -42,7 +42,7 @@ blume <command> [options]
|
|
|
42
42
|
- `blume dev --content-dir <dir>` — scan a different content folder without editing `blume.config.ts`.
|
|
43
43
|
- `blume dev --debug` — verbose Astro/Vite logging for troubleshooting.
|
|
44
44
|
- `blume dev --preview` / `blume build --preview` — include drafts and unpublished CMS content.
|
|
45
|
-
- `blume build --no-strict` — build despite diagnostic errors. By default `blume build` fails (exit 1) on any error diagnostic, because pages that fail frontmatter validation are dropped from the output; with `--no-strict` the build succeeds and reports how many pages are missing. `blume dev --strict` opts dev into the same fail-fast behavior.
|
|
45
|
+
- `blume build --no-strict` — build despite diagnostic errors. By default `blume build` fails (exit 1) on any error diagnostic, because pages that fail frontmatter validation, and `.mdx` pages that don't [parse](/docs/content#markdown-and-mdx), are dropped from the output; with `--no-strict` the build succeeds and reports how many pages are missing. A failure only the build itself finds, such as a page that throws while it renders, still fails it. `blume dev --strict` opts dev into the same fail-fast behavior.
|
|
46
46
|
- `blume build --analyze` — print the client JavaScript bundle sizes (largest first) after the build.
|
|
47
47
|
- `blume build --budget-js <kb> --budget-css <kb>` — fail the build when total client JavaScript/CSS exceeds the budget, turning a performance target into a CI gate.
|
|
48
48
|
- `blume build --isolated` — build into a throwaway `.blume-verify/` runtime (and its own `dist/`) instead of `.blume/`, so a running `blume dev` server and your real `dist/` are left untouched. See [Verifying while the dev server runs](#verifying-while-the-dev-server-runs).
|
|
@@ -107,3 +107,5 @@ Add a `tsconfig.json` extending Astro's config to your project root so authored
|
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
Without a project `tsconfig.json`, only the generated runtime is checked.
|
|
110
|
+
|
|
111
|
+
The build reads this file too, to resolve imports, so an `extends` or `references` entry that doesn't resolve (a package that isn't installed, a file that was moved, a framework's generated tsconfig that doesn't exist yet) stops `blume build`, `blume dev`, and `blume check` with `BLUME_TSCONFIG_EXTENDS`, at the line that names it. Install, restore, or generate the file, or remove the entry.
|
package/docs/cli/validate.mdx
CHANGED
|
@@ -9,14 +9,16 @@ description: blume validate checks every link in your content — pages, anchors
|
|
|
9
9
|
blume validate
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
- **Internal page links** (`/guides/intro`, `./sibling`) must resolve to a real page — broken ones are reported as errors. Every link form Markdown and MDX render is read: inline links, including one whose label wraps onto the next line; reference-style links, checked at their `[label]: /target` definition; autolinks (`<https://…>`, in `.md`); and a component's string `href` (`<Card href="./install">`). A lowercase HTML `<a href>` ships
|
|
13
|
-
- **Anchor links** (`#section`, `/guides/intro#setup`) must match an anchor on the target page — a heading's id (generated or [pinned](/docs/content/syntax#custom-anchors))
|
|
14
|
-
- **
|
|
12
|
+
- **Internal page links** (`/guides/intro`, `./sibling`) must resolve to a real page — broken ones are reported as errors. Every link form Markdown and MDX render is read: inline links, including one whose label wraps onto the next line; reference-style links, checked at their `[label]: /target` definition (the first one, when a label is defined twice, since that's the one that renders); autolinks (`<https://…>`, in `.md`); and a component's string `href` (`<Card href="./install">`). A root-relative link to a Markdown file in your content (`/guides/setup.md`) is checked at the page that file publishes, where the build points it; one naming no file there is checked as the page's [Markdown copy](/docs/discoverability/markdown#raw-markdown). A link's target is read the way the renderer reads it, so `[x](<https://example.com/a(b>)` points at `https://example.com/a(b` and `.png)` at `image(1).png`, with any spaces around it and a title in any of its quotes (`"…"`, `'…'`, or `(…)`) after it. Links in code (fenced, including a fence inside a block quote, or inline) and in comments (`<!-- … -->` in `.md`, `{/* … */}` in `.mdx`) never render, so they aren't checked. A lowercase HTML `<a href>` to a page ships as written, so it's checked the way a browser reads it: a relative path resolves against the page's URL, and no [`basePath`](/docs/deployment#mount-the-docs-under-a-path) is added (a root-relative one gains a [deployment `base`](/docs/deployment#subpath-deploys), as every link does). An `href={…}` expression isn't checked.
|
|
13
|
+
- **Anchor links** (`#section`, `/guides/intro#setup`) must match an anchor on the target page — a heading's id (generated or [pinned](/docs/content/syntax#custom-anchors)), a raw HTML element's `id` attribute, or an `<a name>` — with misses reported as warnings. Ids inside code blocks, inline code, HTML comments, and `<Prompt>` blocks don't count.
|
|
14
|
+
- **Other link schemes** (`mailto:`, `tel:`, an app's `vscode:` deep link) aren't checked: whether a reader's browser or an installed app handles one can't be known. ReadMe's own link schemes are the exception: `doc:`, `ref:`, `page:`, `changelog:`, and `blog:` only resolve on ReadMe and ship as dead links anywhere else, so each is reported as a warning. Link the page by its path instead.
|
|
15
|
+
- **Asset links** are checked where the file lives: an absolute path (`/logo.png`) against the `public/` directory, a relative image embed (``, or a card's `<Card img="./cover.png">`) against the page's own folder. A relative link to any other file (`[spec](./spec.pdf)`, or an `<a href>` or a component's `href`) is checked against the page's own folder too, since Blume [publishes a file there](/docs/content/syntax#links-and-images) with the page; one that names no file beside the page resolves as a site route against `public/`. A media element's `src` (`<img>`, `<source>`, `<video>`, or `<audio>`, as raw HTML in `.md` or an element in `.mdx`) is checked the same way: a relative one is found beside the page, or else where the browser requests it, against `public/`. A project with no `public/` folder ships no public files, so an absolute asset path there is reported missing. An `.html` link (`./setup.html`, `/guides/setup.html`) is a file link too: Blume serves pages at their routes, never at `.html` URLs, so unless `public/` has that file, the link is reported, with the page's route as the fix when a page matches it.
|
|
16
|
+
- **Redirect targets** in [`redirects`](/docs/deployment#redirects) must lead somewhere: an exact internal `to` to a page, a file, or another redirect, and a [pattern](/docs/deployment#pattern-redirects) `to` to a path with something served under its literal start (`/v2/` in `/v2/:slug*`). One that leads nowhere is a warning, located at its `to` in `blume.config.ts`. A link to a redirect's `from` is valid either way. External targets aren't checked.
|
|
15
17
|
- **External links** are only checked with [`--external`](#flags) (off by default since it requires the network). A dead link is an error: a 404 or 410, or a host name that doesn't resolve. Anything else that fails is a warning, since it's more often the other site or the network than the link: any other error status (a 401 or 403 from a site that turns bots away, a 429 rate limit, a 5xx outage), a refused or dropped connection, or no answer within 10 seconds. To leave out URLs that can't be checked from where the command runs, like a placeholder domain, a local server, or a site that turns bots away, pass [`--ignore`](#flags). A bare URL that GitHub-flavored Markdown links on its own, with no link syntax around it, isn't read; [`blume audit --external`](/docs/cli/audit) checks it in the built site.
|
|
16
18
|
|
|
17
19
|
## What counts as a page
|
|
18
20
|
|
|
19
|
-
Links resolve against everything the built site serves, not just Markdown pages: custom [`.astro` pages](/docs/advanced/custom-pages), the generated [changelog](/docs/advanced/changelog) index, every configured [redirect](/docs/deployment#redirects), and, on a [multi-language site](/docs/content/i18n), an untranslated page's fallback URL under each locale. A page that fails to parse is reported alongside the link findings, because a page that never loads is a link-validation blind spot rather than a clean result.
|
|
21
|
+
Links resolve against everything the built site serves, not just Markdown pages: custom [`.astro` pages](/docs/advanced/custom-pages), [API reference](/docs/references/openapi) pages, the generated [changelog](/docs/advanced/changelog) index, every configured [redirect](/docs/deployment#redirects), and, on a [multi-language site](/docs/content/i18n), an untranslated page's fallback URL under each locale. The files Blume writes beside your pages count too, while the config has them on: `/llms.txt` and `/llms-full.txt`, the sitemap, `/robots.txt`, the RSS feeds, `/openapi.json`, `/agent-readability.json`, `/skill.md`, and the `.well-known` discovery files such as `/.well-known/agent-skills/index.json`. So does a folder in `public/` with an `index.html`, at `/demo` or `/demo/` for `public/demo/index.html`, as a static host serves it. A page that fails to load, with invalid front matter or `.mdx` that doesn't [parse](/docs/content#markdown-and-mdx) (`BLUME_MDX_SYNTAX`), is reported alongside the link findings, because a page that never loads is a link-validation blind spot rather than a clean result.
|
|
20
22
|
|
|
21
23
|
## Flags
|
|
22
24
|
|
|
@@ -29,10 +31,11 @@ Links resolve against everything the built site serves, not just Markdown pages:
|
|
|
29
31
|
|
|
30
32
|
| Code | Severity | Meaning |
|
|
31
33
|
| --- | --- | --- |
|
|
32
|
-
| `BLUME_BROKEN_LINK` | error | An internal link points at a route no page serves. |
|
|
34
|
+
| `BLUME_BROKEN_LINK` | error | An internal link points at a route no page serves. When it's a relative link to a file that exists but whose name, or a folder's, starts with `_`, the fix says so: that file is a [partial](/docs/content/includes#partials), which isn't published. |
|
|
33
35
|
| `BLUME_BROKEN_ANCHOR` | warning | The page exists but has no anchor matching the fragment. |
|
|
34
|
-
| `BLUME_BROKEN_ASSET` | warning | An absolute path isn't in `public/`,
|
|
35
|
-
| `
|
|
36
|
+
| `BLUME_BROKEN_ASSET` | warning | An absolute path isn't in `public/`, a relative image embed isn't beside the page, an `.html` link names no file in `public/`, or a media `src` names a file the site doesn't serve at that URL. |
|
|
37
|
+
| `BLUME_BROKEN_REDIRECT` | warning | A redirect's internal `to` leads to no page, file, or other redirect. |
|
|
38
|
+
| `BLUME_UNSUPPORTED_LINK_SCHEME` | warning | A link uses one of ReadMe's link schemes (`doc:`, `ref:`, `page:`, `changelog:`, `blog:`), which browsers can't follow. |
|
|
36
39
|
| `BLUME_DEAD_LINK` | error or warning | An external link (with `--external`) returned 404/410 or its host doesn't resolve (error), or it got any other error status, no connection, or no answer in time (warning). |
|
|
37
40
|
|
|
38
41
|
The exit code is the contract: errors exit non-zero, and `--strict` makes warnings do the same.
|
|
@@ -393,6 +393,8 @@ analytics: [
|
|
|
393
393
|
|
|
394
394
|
`attributes` is a map of extra HTML attributes (`data-*`, `id`, …) spread onto the tag, and `strategy` adds `async` or `defer` to external scripts.
|
|
395
395
|
|
|
396
|
+
A root-relative `src` points at a file in `public/` (`src: "/js/redirects.js"` for `public/js/redirects.js`), so under a [`deployment.base`](/docs/deployment#subpath-deploys) it gets the base, like a link does: with `base: "/docs"`, the tag loads `/docs/js/redirects.js`. A `src` that already starts with the base is left as written, and an absolute or protocol-relative URL passes through, so a script served outside the site's base takes its full URL.
|
|
397
|
+
|
|
396
398
|
## Options
|
|
397
399
|
|
|
398
400
|
| Adapter | Option | Default | Description |
|
|
@@ -22,6 +22,8 @@ export default defineComponents({
|
|
|
22
22
|
|
|
23
23
|
Keys are the names you write in MDX (`<Callout>`, `<Pricing>`). Use the `.tsx` filename when you import React components.
|
|
24
24
|
|
|
25
|
+
A capitalized tag that's neither a built-in, an [island](/docs/content/islands), nor an override fails the page when it renders, so `blume dev`, `blume build`, and `blume check` warn about it first as `BLUME_UNKNOWN_COMPONENT`, once per tag, naming every page that uses it.
|
|
26
|
+
|
|
25
27
|
### Reference form
|
|
26
28
|
|
|
27
29
|
Every override — in `mdx` or `layout` — accepts three forms:
|
|
@@ -104,7 +106,7 @@ Wired slots (names are case-sensitive; any other key under `layout` renders nowh
|
|
|
104
106
|
|
|
105
107
|
The `mobile` variant also receives the [page actions](/docs/content/navigation#page-actions) as its children (an empty element the actions move into from the right rail below 1,280px), so render a `<slot />` in it to keep them on narrower screens. It renders on a page with no headings as well, with `headings` empty, so the actions still show there.
|
|
106
108
|
|
|
107
|
-
`PageHeader` and `PageFooter` have no built-in component — they render nothing until you set them, which makes them handy injection points for a promo banner or a "last updated" note. The built-in `Footer` holds the only links to your repository and social profiles, so a `Footer` override (the place for a marketing footer the config can't express) should keep them. With `consent` set, also keep a way to reopen it: any element with `data-blume-consent-open` works as the [Cookie settings](/docs/configuration/consent#changing-an-answer) link.
|
|
109
|
+
`PageHeader` and `PageFooter` have no built-in component — they render nothing until you set them, which makes them handy injection points for a promo banner or a "last updated" note. `PageFooter` renders at the foot of every page Blume builds from your content, API operation pages included, with `Feedback` and `Pagination` after it. A page in [`custom` or `frame` mode](/docs/content/frontmatter#layout) drops that page-end area along with its title and breadcrumbs. A [custom page](/docs/advanced/custom-pages) under `pages/` renders the layout it wraps itself in: `RootLayout` takes slot overrides through its `layout` prop, and `PageLayout` has no page-end area. The built-in `Footer` holds the only links to your repository and social profiles, so a `Footer` override (the place for a marketing footer the config can't express) should keep them. With `consent` set, also keep a way to reopen it: any element with `data-blume-consent-open` works as the [Cookie settings](/docs/configuration/consent#changing-an-answer) link.
|
|
108
110
|
|
|
109
111
|
Layout slots accept the same [three reference forms](#reference-form) as MDX overrides, so a slot can be a path string or a hydrated descriptor (`{ component, client }`) when you want an interactive header or footer.
|
|
110
112
|
|
|
@@ -101,7 +101,7 @@ export default defineConfig({
|
|
|
101
101
|
| `description` | — | Default meta description, used for SEO and OG. |
|
|
102
102
|
| `logo` | — | Brand mark and/or wordmark shown in the header. |
|
|
103
103
|
| `banner` | — | Site-wide announcement bar above the header. |
|
|
104
|
-
| `footer` | — | A row of links and social profile icons below the content. |
|
|
104
|
+
| `footer` | — | A copyright line, a row of links, and social profile icons below the content. |
|
|
105
105
|
|
|
106
106
|
### Logo
|
|
107
107
|
|
|
@@ -204,10 +204,11 @@ A translated banner keys dismissal on the default locale's text, so one dismissa
|
|
|
204
204
|
|
|
205
205
|
### Footer
|
|
206
206
|
|
|
207
|
-
Every page ends with a footer: one row, as tall as the header, with your links on one side
|
|
207
|
+
Every page ends with a footer: one row, as tall as the header, with your links on one side, social profile icons on the other, and a copyright line centered between them. The footer is the only place Blume links your social profiles and repository, so the [`github`](#github) repository comes first among the icons whenever it's set. `footer` adds the rest:
|
|
208
208
|
|
|
209
209
|
```ts blume.config.ts lineNumbers
|
|
210
210
|
footer: {
|
|
211
|
+
copyright: "© 2026 Acme, Inc.",
|
|
211
212
|
links: [
|
|
212
213
|
{ label: "Pricing", href: "https://acme.dev/pricing" },
|
|
213
214
|
{ label: "Changelog", href: "/changelog" },
|
|
@@ -220,9 +221,9 @@ footer: {
|
|
|
220
221
|
},
|
|
221
222
|
```
|
|
222
223
|
|
|
223
|
-
`links` appear in the order you write them. Write internal links as if mounted at root; an external link opens in a new tab. On a [multilingual](/docs/content/i18n#per-locale-navigation) site, a `label` can be a map of locale code to text, and an internal link moves into the reader's locale whenever that locale serves the page. `socials` maps a platform to its profile URL, and the icons appear in the order you write them. The platforms are `bluesky`, `discord`, `facebook`, `github`, `hacker-news`, `instagram`, `linkedin`, `medium`, `podcast`, `reddit`, `slack`, `telegram`, `threads`, `website`, `x`, and `youtube`. A `github` social replaces the repository link; hide that link with [`navigation.repo`](/docs/content/navigation#repository-link).
|
|
224
|
+
`copyright` is plain text, so write `©` itself rather than `©`. For a year that keeps itself current, use a template literal: `` `© ${new Date().getFullYear()} Acme, Inc.` ``. `links` appear in the order you write them. Write internal links as if mounted at root; an external link opens in a new tab. On a [multilingual](/docs/content/i18n#per-locale-navigation) site, `copyright` and a `label` can each be a map of locale code to text, and an internal link moves into the reader's locale whenever that locale serves the page. `socials` maps a platform to its profile URL, and the icons appear in the order you write them. The platforms are `bluesky`, `discord`, `facebook`, `github`, `hacker-news`, `instagram`, `linkedin`, `medium`, `podcast`, `reddit`, `slack`, `telegram`, `threads`, `website`, `x`, and `youtube`. A `github` social replaces the repository link; hide that link with [`navigation.repo`](/docs/content/navigation#repository-link).
|
|
224
225
|
|
|
225
|
-
A site with no links, profiles, or repository has no footer. Custom pages built on `PageLayout` show it too, unless they fill the layout's own `footer` slot. To replace it entirely, override the [`Footer` layout slot](/docs/configuration/customization#layout-slots).
|
|
226
|
+
A site with no copyright, links, profiles, or repository has no footer. Custom pages built on `PageLayout` show it too, unless they fill the layout's own `footer` slot. To replace it entirely, override the [`Footer` layout slot](/docs/configuration/customization#layout-slots).
|
|
226
227
|
|
|
227
228
|
## Content
|
|
228
229
|
|
|
@@ -238,7 +239,7 @@ content: {
|
|
|
238
239
|
| --- | --- | --- |
|
|
239
240
|
| `root` | `"docs"` | Folder Blume scans for content. Shorthand for a single `filesystem()` source; not allowed beside `sources`. |
|
|
240
241
|
| `include` | `["**/*.{md,mdx}"]` | Globs that match content files. Shorthand, like `root`. |
|
|
241
|
-
| `exclude` | `["**/_*", "**/.*"]` | Globs to ignore
|
|
242
|
+
| `exclude` | `["**/_*", "**/.*"]` | Globs to ignore. Yours add to the defaults, which skip underscore- and dot-files; a `!` entry drops a pattern, so `"!**/_*"` publishes `_`-prefixed files. Shorthand, like `root`. |
|
|
242
243
|
| `sources` | one `filesystem()` | Content source adapters from `blume/sources`, replacing the shorthand. See [Content sources](/docs/content/sources). |
|
|
243
244
|
| `pages` | `"pages"` | Folder for custom `.astro` pages. |
|
|
244
245
|
| `defaultType` | `"doc"` | Page `type` used when frontmatter omits it. |
|
|
@@ -365,7 +366,7 @@ lastModified: "git",
|
|
|
365
366
|
| `"git"` | Read the date from git history (commit dates). |
|
|
366
367
|
| `"frontmatter"` | Never run git — use only the `lastModified` frontmatter field. |
|
|
367
368
|
|
|
368
|
-
The git source reads the most recent commit that touched each file, so it works in any git repository — including monorepos — and needs the repo's history at build time. CI platforms usually check out a shallow clone, which silently drops most dates (the build warns with `BLUME_SHALLOW_GIT_HISTORY` when that happens): on Vercel, set the `VERCEL_DEEP_CLONE=true` environment variable; with `actions/checkout`, set `fetch-depth: 0`. A page's own `lastModified` frontmatter always wins, which is handy for pinning a date or for files that aren't committed yet:
|
|
369
|
+
The git source reads the most recent commit that touched each file, so it works in any git repository — including monorepos — and needs the repo's history at build time. It follows renames, as `git log --follow` does: renaming `page.md` to `page.mdx`, or moving a file to another folder under the same content root, keeps the page's date as long as the commit leaves its content unchanged. A rename that also edits the file dates the page at that commit, and so does moving a file in from outside the content root. CI platforms usually check out a shallow clone, which silently drops most dates (the build warns with `BLUME_SHALLOW_GIT_HISTORY` when that happens): on Vercel, set the `VERCEL_DEEP_CLONE=true` environment variable; with `actions/checkout`, set `fetch-depth: 0`. A page's own `lastModified` frontmatter always wins, which is handy for pinning a date or for files that aren't committed yet:
|
|
369
370
|
|
|
370
371
|
```mdx page.mdx
|
|
371
372
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Rate limiting
|
|
3
|
-
description: Limit how often one reader can call the assistant, the API playground proxy, and server-side search, on by default, with the count kept in memory, Upstash, or
|
|
3
|
+
description: Limit how often one reader can call the assistant, the API playground proxy, and server-side search, on by default, with the count kept in memory, Upstash, Cloudflare, or Unkey.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
The server routes a reader can call cost you something each time: the [assistant](/docs/configuration/assistant) spends model tokens, the [API playground](/docs/references/openapi#cors-and-the-proxy) proxy relays requests to your API, and [Mixedbread search](/docs/configuration/search#mixedbread) runs a paid query. Blume limits how often one reader, identified by IP address, can call each of them. A reader over the limit gets `429 Too Many Requests` with a `Retry-After` header, and the assistant tells them to try again in a few minutes.
|
|
@@ -25,6 +25,7 @@ Each route keeps its own count, so a busy playground session doesn't use up the
|
|
|
25
25
|
| `memory()` | The server's memory (the default) | Exactly on one server; per instance on serverless hosts |
|
|
26
26
|
| `upstash()` | [Upstash Redis](https://upstash.com) | Exactly, on every host |
|
|
27
27
|
| `cloudflare()` | Cloudflare's Workers rate limiting | Per Cloudflare location |
|
|
28
|
+
| `unkey()` | [Unkey](https://unkey.com) | On every host; regions catch up within moments |
|
|
28
29
|
|
|
29
30
|
### Memory
|
|
30
31
|
|
|
@@ -68,6 +69,24 @@ export default defineConfig({
|
|
|
68
69
|
|
|
69
70
|
The binding's namespace comes from the Worker's name, so two sites on one account don't share a count. Set `namespaceId` to choose it yourself.
|
|
70
71
|
|
|
72
|
+
### Unkey
|
|
73
|
+
|
|
74
|
+
`unkey()` keeps the count in [Unkey's rate limiting](https://www.unkey.com/docs/api-management/ratelimiting/overview), which every instance shares. Create a root key with the `ratelimit.*.limit` permission, plus `ratelimit.*.create_namespace` so Unkey can create the namespace on the first request, then set it as `UNKEY_ROOT_KEY`. Blume talks to Unkey's REST API, so there's nothing to install. Until the key is set, the routes count in memory and `blume build` warns.
|
|
75
|
+
|
|
76
|
+
```ts blume.config.ts lineNumbers
|
|
77
|
+
import { unkey } from "blume/ratelimit";
|
|
78
|
+
|
|
79
|
+
rateLimit: unkey(),
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The namespace is `docs` unless you name another with `namespace`. Name the variable that holds the key with `rootKeyEnv`:
|
|
83
|
+
|
|
84
|
+
```ts blume.config.ts lineNumbers
|
|
85
|
+
rateLimit: unkey({ namespace: "acme-docs", rootKeyEnv: "DOCS_UNKEY_ROOT_KEY" }),
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Unkey counts in each region and shares the counts between regions within moments, so a short burst split across regions can get a few more requests through than the limit. Every count fails with a key Unkey refuses, like one missing those permissions, and a request a shared store fails to count is let through, so if the server logs `Rate limiting failed`, check the key.
|
|
89
|
+
|
|
71
90
|
## Behind a reverse proxy
|
|
72
91
|
|
|
73
92
|
Vercel, Netlify, and Cloudflare tell Blume each reader's address. A `node()` server behind a reverse proxy, like nginx or Caddy, sees every request come from the proxy, so every reader shares one count and a busy site hits the limit for everyone. List the host the proxy answers for in `allowedDomains`:
|
|
@@ -36,6 +36,8 @@ Named presets: `blue` (default), `green`, `orange`, `pink`, `purple`, `red`, and
|
|
|
36
36
|
|
|
37
37
|
A string applies to both color modes; pass an object for [a different accent per mode](#dark-mode-colors).
|
|
38
38
|
|
|
39
|
+
A value that's neither a preset nor a CSS color, like `"deep purple"` or a hex value without its `#`, warns `BLUME_THEME_COLOR_INVALID` at the line in `blume.config.ts` that sets it, since browsers ignore the styles that use it. The same check covers `action`, `background`, and the [Open Graph card's](/docs/discoverability/open-graph) `seo.og.palette`. Custom properties (`var(--brand)`), `color-mix()`, and the other color functions pass as written.
|
|
40
|
+
|
|
39
41
|
Text on an accent or action fill, like a button label or a step number, is white while white meets AA on that color, and dark otherwise. A light accent gets dark labels without any extra config. [`blume audit`](/docs/cli/audit#theme-contrast-low) checks a custom accent, action, or background against the same bar.
|
|
40
42
|
|
|
41
43
|
### Radius
|
|
@@ -231,6 +233,8 @@ Set a token under `:root` for light mode and under `:root[data-theme="dark"]` fo
|
|
|
231
233
|
| `--blume-code-highlight`, `--blume-code-highlight-border` | Background and left rule of a highlighted code line (`// [!code highlight]` or a `{1,4-5}` range) |
|
|
232
234
|
| `--blume-code-add`, `--blume-code-add-border` | Background and left rule of an added line (`// [!code ++]`) |
|
|
233
235
|
| `--blume-code-remove`, `--blume-code-remove-border` | Background and left rule of a removed line (`// [!code --]`) |
|
|
236
|
+
| `--blume-code-error`, `--blume-code-error-border` | Background and left rule of an error line (`// [!code error]`) |
|
|
237
|
+
| `--blume-code-warning`, `--blume-code-warning-border` | Background and left rule of a warning line (`// [!code warning]`) |
|
|
234
238
|
| `--blume-code-word`, `--blume-code-word-border` | Background and outline of a highlighted word (`// [!code word:…]`) |
|
|
235
239
|
| `--blume-content-width` | Max width of the prose column — article, breadcrumb, table of contents, feedback, and pagination (default `42rem`) |
|
|
236
240
|
| `--blume-radius` | Corner radius |
|
|
@@ -248,7 +252,7 @@ Set a `--blume-font-*` token to any font stack to use a font outside the curated
|
|
|
248
252
|
|
|
249
253
|
## Tailwind utilities
|
|
250
254
|
|
|
251
|
-
Blume's theme is built with Tailwind v4 internally, and your project's `.astro`, `.
|
|
255
|
+
Blume's theme is built with Tailwind v4 internally, and your project's `.astro`, `.jsx`, `.mdx`, `.ts`, and `.tsx` files are scanned too — so you can style custom components and pages with utility classes, no Tailwind setup required. Every token is exposed as a utility, so your components track the theme automatically:
|
|
252
256
|
|
|
253
257
|
| Token | Utilities |
|
|
254
258
|
| --------------------------- | -------------------------- |
|
|
@@ -5,6 +5,8 @@ description: Cards, steps, tabs, accordions, badges, code groups, frames, trees,
|
|
|
5
5
|
|
|
6
6
|
Blume ships an accessible, themeable component set available in any `.mdx` page with **no imports**. Each one is shown below with a live preview and its source. Components are vanilla and React-free; React switches on only when your project uses it — any `.tsx` or `.jsx` file in the project, a React [island](/docs/content/islands), [`<Component>`](#component) example, or [component override](/docs/configuration/customization) — or when the [assistant](/docs/configuration/assistant) is enabled.
|
|
7
7
|
|
|
8
|
+
A component ignores props it doesn't take. Most show their children, so other docs tools' spellings can render empty: VitePress's `<Badge type="tip" text="beta" />` is a Badge with no children, which shows nothing. Blume warns about a childless component given props it doesn't take as `BLUME_UNKNOWN_PROP`, with the props it does take. Write the content between the tags instead: `<Badge>beta</Badge>`.
|
|
9
|
+
|
|
8
10
|
## Card and CardGroup
|
|
9
11
|
|
|
10
12
|
Cards link to a destination with an icon, title, and short blurb. Group them with `CardGroup` for a responsive grid. Reach for them on landing pages, section indexes, and “next steps” — anywhere you’re guiding the reader onward.
|
|
@@ -31,7 +33,7 @@ Cards link to a destination with an icon, title, and short blurb. Group them wit
|
|
|
31
33
|
|
|
32
34
|
`Card` takes `title`, an optional `href` (omit it for a non-clickable card), and an `icon` from Blume's built-in icon set. `CardGroup` takes `cols` (default `2`).
|
|
33
35
|
|
|
34
|
-
A card also takes `img`, an image across its top (or beside the text from the `sm` breakpoint up, with `horizontal`); `cta`, a call-to-action line in the accent color beneath the text; `arrow`, an arrow after the title and the CTA (shown by default only for external links); `type`, which tints the card and picks a matching icon the way a callout does (`note`, `info`, `tip`, `check`, `warning`, or `danger`); and `color`, any CSS color for the icon.
|
|
36
|
+
A card also takes `img`, an image across its top (or beside the text from the `sm` breakpoint up, with `horizontal`), given like a Markdown image's path: a file next to the page (`./cover.png`), a path under `public/`, or a URL; `cta`, a call-to-action line in the accent color beneath the text; `arrow`, an arrow after the title and the CTA (shown by default only for external links); `type`, which tints the card and picks a matching icon the way a callout does (`note`, `info`, `tip`, `check`, `warning`, or `danger`); and `color`, any CSS color for the icon.
|
|
35
37
|
|
|
36
38
|
## Steps
|
|
37
39
|
|
|
@@ -119,6 +121,22 @@ pip install acme-commerce
|
|
|
119
121
|
|
|
120
122
|
The first view shows until the reader picks another. Blume remembers that pick across pages written in views, and writes it to the URL as `?view=Python`, so a link opens on the same view. A link to a heading inside a view opens that view. Use `<View>` when most of the page changes with the choice, and [Tabs](#tabs) when only one part of the page does. The agent-facing Markdown includes every view, each under its name.
|
|
121
123
|
|
|
124
|
+
## Callout
|
|
125
|
+
|
|
126
|
+
`<Callout>` is the component behind [callout directives](/docs/content/syntax#callouts): `:::warning[Heads up]` renders `<Callout type="warning" title="Heads up">`. Write the component itself when a callout needs its own icon or color, which a directive can't set.
|
|
127
|
+
|
|
128
|
+
<Callout type="tip" title="Ship it" icon="rocket">
|
|
129
|
+
Run `blume build` before you deploy.
|
|
130
|
+
</Callout>
|
|
131
|
+
|
|
132
|
+
```astro
|
|
133
|
+
<Callout type="tip" title="Ship it" icon="rocket">
|
|
134
|
+
Run `blume build` before you deploy.
|
|
135
|
+
</Callout>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`type` sets the tint and the default icon: `note`, `info` (the default), `tip`, `success` (or `check`), `warning`, or `danger`. The aliases `caution`, `error`, `important`, and `warn` work only in the `:::` form. `title` adds a bold first line. `icon` replaces the type's icon and takes the same inputs as [`<Icon>`](#icon): a Lucide name, an image path or URL, or an inline SVG. `color`, any CSS color, replaces the type's tint: the border, the icon, and the body text take that color over the page background.
|
|
139
|
+
|
|
122
140
|
## Badge
|
|
123
141
|
|
|
124
142
|
A small inline label for status or metadata — version tags, “new” or “beta” markers, stability levels. The `variant` tunes the color to the meaning.
|
|
@@ -225,7 +243,7 @@ Illustrate a project or folder layout. Wrap a normal Markdown list and Blume sty
|
|
|
225
243
|
|
|
226
244
|
## Accordion
|
|
227
245
|
|
|
228
|
-
Stack related collapsibles in a single bordered container with dividers between them — FAQs, optional steps, or long examples. Each child is an `AccordionItem` (`title`, optional `icon`, `description`, `defaultOpen`). For a single standalone disclosure, use [Expandable](#expandable).
|
|
246
|
+
Stack related collapsibles in a single bordered container with dividers between them — FAQs, optional steps, or long examples. Each child is an `AccordionItem` (`title`, optional `icon`, `description`, `defaultOpen`). The `title` renders inline Markdown, so code spans, emphasis, and links in it show as they would in a sentence; raw HTML in it shows as text. For a single standalone disclosure, use [Expandable](#expandable).
|
|
229
247
|
|
|
230
248
|
<Accordion>
|
|
231
249
|
<AccordionItem title="Does it support MDX?">
|
|
@@ -249,7 +267,7 @@ Stack related collapsibles in a single bordered container with dividers between
|
|
|
249
267
|
|
|
250
268
|
## Expandable
|
|
251
269
|
|
|
252
|
-
A lightweight inline disclosure for nested detail — expanding a field's sub-properties or an optional aside. `title` labels the toggle (defaults to “Show more”); set `defaultOpen` to start expanded.
|
|
270
|
+
A lightweight inline disclosure for nested detail — expanding a field's sub-properties or an optional aside. `title` labels the toggle (defaults to “Show more”) and renders inline Markdown, as an accordion item's does; set `defaultOpen` to start expanded.
|
|
253
271
|
|
|
254
272
|
<Expandable title="Show advanced options">
|
|
255
273
|
These settings are optional and rarely need changing.
|
|
@@ -295,7 +313,7 @@ Lay cards or blocks out in a responsive grid of equal columns that reflows on mo
|
|
|
295
313
|
|
|
296
314
|
## CodeGroup
|
|
297
315
|
|
|
298
|
-
Group several code blocks into one tabbed switcher — a tab per language or file. The tab label is each block's title (the text after the language), and the group's copy button sits in the tab bar and copies the block that is showing. Add `dropdown` to switch with a menu instead of a tab bar.
|
|
316
|
+
Group several code blocks into one tabbed switcher — a tab per language or file. The tab label is each block's title (the text after the language), or its language's name (`TypeScript`, `Python`) for a block without one, and the group's copy button sits in the tab bar and copies the block that is showing. Add `dropdown` to switch with a menu instead of a tab bar.
|
|
299
317
|
|
|
300
318
|
<CodeGroup>
|
|
301
319
|
|
|
@@ -367,7 +385,7 @@ Wrap an image or any visual in a centered, bordered frame with an optional `capt
|
|
|
367
385
|
|
|
368
386
|
## YouTube
|
|
369
387
|
|
|
370
|
-
Embed a YouTube video in a responsive, privacy-friendly (`youtube-nocookie.com`) 16:9 frame that ships no client JavaScript. Pass a video `id` or a full `url`, plus an optional `title` (for accessibility) and a `start` time in seconds.
|
|
388
|
+
Embed a YouTube video in a responsive, privacy-friendly (`youtube-nocookie.com`) 16:9 frame that ships no client JavaScript. Pass a video `id` or a full `url`, plus an optional `title` (for accessibility) and a `start` time in seconds. A playlist `url` (`youtube.com/playlist?list=…` or `youtube.com/embed/videoseries?list=…`) embeds the whole playlist.
|
|
371
389
|
|
|
372
390
|
<YouTube id="aqz-KE-bpKQ" title="Big Buck Bunny" />
|
|
373
391
|
|
|
@@ -468,7 +486,7 @@ A clickable preview that leads with a visual — an icon or image — above a ti
|
|
|
468
486
|
|
|
469
487
|
## Prompt
|
|
470
488
|
|
|
471
|
-
A single row with a label and a copy button. The `description` (Markdown) is the visible label; the body is the prompt itself — hidden, and copied to the clipboard as Markdown, with its links, lists, and code intact, when the **Copy prompt** button is pressed. `actions` controls the buttons (e.g. `["copy", "cursor"]`).
|
|
489
|
+
A single row with a label and a copy button. The `description` (Markdown) is the visible label; the body is the prompt itself — hidden, and copied to the clipboard as Markdown, with its links, lists, and code intact, when the **Copy prompt** button is pressed. Its punctuation copies as you typed it: straight quotes, `--`, and `...` stay as written, though prose elsewhere on the page shows them as curly quotes, dashes, and ellipses. `actions` controls the buttons (e.g. `["copy", "cursor"]`).
|
|
472
490
|
|
|
473
491
|
<Prompt
|
|
474
492
|
description="Ask the model to **document** an endpoint."
|
|
@@ -781,6 +799,8 @@ import CodeBlock from "blume/components/content/CodeBlock.astro";
|
|
|
781
799
|
|
|
782
800
|
`title` sets the header label — a filename, say — which otherwise shows the language, and `icons={false}` hides the language's brand icon, as [`markdown.code.icons`](/docs/content/syntax#code-blocks) does for fences.
|
|
783
801
|
|
|
802
|
+
Without `code`, `CodeBlock` renders its children as written, so a fenced block wrapped in `<CodeBlock>…</CodeBlock>` (the way Fern and Mintlify write code) shows as that fence. `title` and the other props don't apply to it then: give the fence its [title](/docs/content/syntax#code-blocks) after the language instead.
|
|
803
|
+
|
|
784
804
|
To highlight to an HTML string yourself (e.g. inside your own component), import the underlying helper from `blume/markdown`:
|
|
785
805
|
|
|
786
806
|
```ts
|
|
@@ -148,7 +148,7 @@ sidebar:
|
|
|
148
148
|
display: page
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
-
`hidden` removes the page from the sidebar and from previous/next pagination. On a folder's `index` page it removes only the page's own row: the group row keeps linking to the page,
|
|
151
|
+
`hidden` removes the page from the sidebar and from previous/next pagination, and so from the sitemap, search, and `llms.txt` (see [Hidden pages](/docs/content/navigation#hidden-pages)). On a folder's `index` page it removes only the page's own row: the group row keeps linking to the page, so previous/next links still pass through it and the page stays in the sitemap, search, and `llms.txt`. On the home page, the root `index` page, it also removes only the row: the page stays in the sitemap, search, and `llms.txt`.
|
|
152
152
|
|
|
153
153
|
`display` sets the render mode of the page's folder group ([per-group overrides](/docs/content/navigation#per-group-overrides)) and is only meaningful on a folder's `index` page under the generated sidebar — anywhere else (a non-index page, the content root's own `index` page, or any page under an explicit `navigation.sidebar`) it has no group to configure, and Blume warns with `BLUME_SIDEBAR_DISPLAY_IGNORED`.
|
|
154
154
|
|
package/docs/content/i18n.mdx
CHANGED
|
@@ -85,7 +85,7 @@ i18n: {
|
|
|
85
85
|
|
|
86
86
|
Each language gets its own sidebar, built from that locale's files — so translations can diverge in structure, ordering, or labels. Folder [`meta.ts`](/docs/content/meta) files resolve per locale, too: under the default `dir` parser, put a `meta.ts` under `fr/guides/` to order the French group independently. Until a locale has one (or a shared `meta.$.ts`), its group mirrors the [fallback](#fallbacks) locale's — that folder's `meta.ts` and the `sidebar.display` its index page sets — so pages that fall back keep the same titles, order, and collapsible groups. Under the `dot` parser translations sit next to the originals, so a folder's `meta.ts` applies to every locale. Everything else about [navigation](/docs/content/navigation) works the same, per language.
|
|
87
87
|
|
|
88
|
-
Header tabs, header links, and the footer are configured, not derived from content, so their labels localize in `blume.config.ts`. Every configured label accepts a per-locale map (`{ en: "Docs", fr: "Documentation" }`) alongside the plain-string form, falling back to the default locale's entry for locales you haven't filled in: tab and dropdown labels ([Tabs](/docs/content/navigation#tabs)), [featured links](/docs/content/navigation#featured-links), [header actions](/docs/content/navigation#header-actions) and the call to action, [footer](/docs/configuration#footer) links,
|
|
88
|
+
Header tabs, header links, and the footer are configured, not derived from content, so their labels localize in `blume.config.ts`. Every configured label accepts a per-locale map (`{ en: "Docs", fr: "Documentation" }`) alongside the plain-string form, falling back to the default locale's entry for locales you haven't filled in: tab and dropdown labels ([Tabs](/docs/content/navigation#tabs)), [featured links](/docs/content/navigation#featured-links), [header actions](/docs/content/navigation#header-actions) and the call to action, [footer](/docs/configuration#footer) links, the [banner](/docs/configuration#banner)'s text and link text, and custom clients in the [Connect to MCP](/docs/discoverability/mcp#connect-to-mcp-menu) menu.
|
|
89
89
|
|
|
90
90
|
```ts blume.config.ts lineNumbers
|
|
91
91
|
navigation: {
|
|
@@ -23,7 +23,7 @@ Here it is live — this next callout is spliced from a shared snippet:
|
|
|
23
23
|
|
|
24
24
|
## Partials
|
|
25
25
|
|
|
26
|
-
Any file whose name (or folder) starts with an underscore is excluded from routing, navigation, search, and sitemaps
|
|
26
|
+
Any file whose name (or folder) starts with an underscore is excluded from routing, navigation, search, and sitemaps — that convention is the natural home for shared snippets. Patterns you add to [`content.exclude`](/docs/configuration#content) add to this rule rather than replacing it; to publish underscore files after all, add `"!**/_*"` to `exclude`:
|
|
27
27
|
|
|
28
28
|
```text
|
|
29
29
|
docs/
|
|
@@ -37,7 +37,9 @@ docs/
|
|
|
37
37
|
|
|
38
38
|
A partial is a normal Markdown or MDX file. Its front matter is stripped when spliced (the including page's front matter wins), and everything else — callouts, code fences, components, math — renders exactly as it would inline. Partials can include other partials; a circular include is reported as an error.
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
Link reference definitions (`[pep 508]: https://peps.python.org/pep-0508/`) cross includes too, so a partial can hold a site's shared link definitions: the page and its other partials can cite a partial's (`[PEP 508]`), and a partial can cite the page's. When the page and a partial both define a label, each uses its own.
|
|
41
|
+
|
|
42
|
+
Relative image references inside a partial keep working: they're rebased onto the including page, so a colocated `` or `<Card img="./cover.png">` next to the partial resolves wherever the partial is spliced. An image's path is rebased in whatever form it's written: in angle brackets (``), with escaped parentheses, or followed by a title in any of its quotes. A link to another file next to the partial (`[spec](./spec.pdf)`, or an `<img src>` or `<a href>` naming one) moves with it too. A link to a page resolves from the including page, as if it were written there.
|
|
41
43
|
|
|
42
44
|
Editing a partial while `blume dev` is running reloads every page that includes it.
|
|
43
45
|
|
|
@@ -77,6 +79,8 @@ Targets must live inside your content root: a file outside it would be silently
|
|
|
77
79
|
|
|
78
80
|
Broken links inside a partial are reported against the partial file, not the pages that splice it, so you fix them where they live.
|
|
79
81
|
|
|
82
|
+
A partial is read in the including page's format, so a `.md` partial that an `.mdx` page includes is read as MDX. MDX has no HTML comments, so the partial's `<!-- … -->` comments are spliced as MDX comments (`{/* … */}`) and stay hidden. Other HTML there has to be valid JSX: an `<img …>` or `<br>` without a closing slash takes in everything after it in the partial, with no error. Blume warns about it as `BLUME_MDX_UNCLOSED_ELEMENT` at the partial's line; close it as `<br />`. Anything else in the partial that MDX can't parse once it's spliced in, like a stray `{`, is a [`BLUME_MDX_SYNTAX`](/docs/content#markdown-and-mdx) warning at the partial's line, and when it fails the build, the build reports it there too, not at the page that includes it.
|
|
83
|
+
|
|
80
84
|
:::note
|
|
81
85
|
Partials are shared across locales and are not translated by `blume translate` — keep partials language-neutral (code, tables, diagrams), or create per-locale partials and include them from each locale's pages.
|
|
82
86
|
:::
|
package/docs/content/index.mdx
CHANGED
|
@@ -16,6 +16,10 @@ Blume renders two kinds of file:
|
|
|
16
16
|
|
|
17
17
|
Reach for `.md` when a page is just prose, and `.mdx` when it needs components or directives. Switching is as simple as renaming the file.
|
|
18
18
|
|
|
19
|
+
In `.mdx`, `{` starts a JavaScript expression and `<` a JSX tag, so text that's fine in `.md` can break a page: a literal brace, an HTML comment (write `{/* … */}`), or an element left open (write `<br />`). Blume parses every `.mdx` page when it reads the project, so `blume dev`, `blume validate`, `blume doctor`, and `blume check` report one that doesn't parse as `BLUME_MDX_SYNTAX`, an error at the line and column where MDX stopped, and `blume build` stops there before it compiles anything. With `--no-strict`, the build leaves the page out and builds the rest of the site. `blume dev` keeps the page, and opening it shows the error.
|
|
20
|
+
|
|
21
|
+
An expression can parse and still fail when the page renders, like `{user.name}` on a page where nothing defines `user`. `blume build` reports that as `BLUME_MDX_UNDEFINED_NAME` at the expression's line, in the page or in the [partial](/docs/content/includes) that holds it. To show braces as text, escape each opening brace (`\{`) or put the text in inline code. For a value every page shares, define a [variable](/docs/content/variables).
|
|
22
|
+
|
|
19
23
|
## Files and routes
|
|
20
24
|
|
|
21
25
|
Each file maps to a route by its path under the content root:
|
|
@@ -40,7 +44,13 @@ Prefix a file or folder with a number and a `-`, `_`, or `.` to control its orde
|
|
|
40
44
|
02-installation.mdx -> /installation
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
A version or
|
|
47
|
+
A version or a date at the start of a name is part of the name, not an order: `1.2.0.mdx` routes to `/1.2.0`, and `2024-01-05-launch.mdx` to `/2024-01-05-launch`. Blume reads these as dates:
|
|
48
|
+
|
|
49
|
+
- An ISO date, `YYYY-MM-DD`: `2024-01-05.mdx` routes to `/2024-01-05`.
|
|
50
|
+
- A day or month first, then a four-digit year, `D-M-YYYY` or `M-D-YYYY` with one or two digits for the day and month: `12-05-2022.mdx` routes to `/12-05-2022`.
|
|
51
|
+
- A year and a month, `YYYY-MM`: `2024-01.mdx` routes to `/2024-01`.
|
|
52
|
+
|
|
53
|
+
A date ends the name or is followed by a `-`, `_`, or `.`, like the rest of a name (`2024-01-recap.mdx`). Earlier Blume versions read the first number of the last two forms as an ordering prefix, so `12-05-2022.mdx` published at `/05-2022` and `2024-01.mdx` at `/01`. Those old URLs now redirect to the new ones, unless another page lives there. Only file and folder names lose a prefix (an Obsidian vault's notes count as files). A frontmatter `slug`, and a page from a [content source](/docs/content/sources) such as a CMS or GitHub Releases, keep the name they were given.
|
|
44
54
|
|
|
45
55
|
Ordering has several layers — see [Navigation](/docs/content/navigation) for the full precedence rules.
|
|
46
56
|
|
package/docs/content/islands.mdx
CHANGED
|
@@ -28,6 +28,8 @@ The filename is the component name, so it **must be a PascalCase identifier**
|
|
|
28
28
|
Islands are for **interactive** UI. For a static component you reuse across pages (a styled callout, a pricing table), use an [MDX override](/docs/configuration/customization) instead — it ships no JavaScript.
|
|
29
29
|
:::
|
|
30
30
|
|
|
31
|
+
An island is the only way to run code in the browser from a page. A JavaScript event handler on a plain HTML element in MDX, like `<button onClick={() => open()}>`, never runs: the page is static HTML, so the function is written into the attribute as text. Blume warns about one as `BLUME_MDX_EVENT_HANDLER` at its line. Move that markup into an island and use the island in the page.
|
|
32
|
+
|
|
31
33
|
## Registering islands in `components.ts`
|
|
32
34
|
|
|
33
35
|
If you'd rather keep islands next to the rest of your components — or give them a different name than the file — register them with `defineComponents` as an `mdx` entry with a `client` mode. That's all an island is: an MDX component that hydrates. Each entry is available in every MDX page, and an entry with the same name as an `islands/` file replaces it.
|
package/docs/content/meta.mdx
CHANGED
|
@@ -23,7 +23,9 @@ export default defineMeta({
|
|
|
23
23
|
|
|
24
24
|
Every field is optional — set only what you want to override.
|
|
25
25
|
|
|
26
|
-
Blume only reads `meta.ts` files from folders your content covers: one under a folder your content `exclude` globs skip, or outside every `include` glob, is never imported. With `root: "."` and `exclude: ["
|
|
26
|
+
Blume only reads `meta.ts` files from folders your content covers: one under a folder your content `exclude` globs skip, or outside every `include` glob, is never imported. With `root: "."` and `exclude: ["src/**"]`, an unrelated `src/lib/meta.ts` is left alone.
|
|
27
|
+
|
|
28
|
+
A `meta.ts` outside every `include` glob is still ignored when its folder is a sidebar group, like a reference's [tag folder](#generated-groups) on a site whose `include` lists only `guides/**`. Blume warns about that one as `BLUME_META_OUTSIDE_INCLUDE`: add an `include` glob that reaches the folder, such as `"api/**/*.{md,mdx}"`, so Blume reads it.
|
|
27
29
|
|
|
28
30
|
## Fields
|
|
29
31
|
|
|
@@ -32,17 +34,21 @@ Blume only reads `meta.ts` files from folders your content covers: one under a f
|
|
|
32
34
|
| `title` | `string` | The group's label. Defaults to the humanized folder name. |
|
|
33
35
|
| `icon` | `string` | Icon shown next to the label. |
|
|
34
36
|
| `order` | `number` | Position among sibling groups and pages. Lower numbers sort first. |
|
|
35
|
-
| `collapsed` | `boolean` | Under the [`group` display mode](/docs/content/navigation#display-modes), whether the group starts collapsed. |
|
|
37
|
+
| `collapsed` | `boolean` | Under the [`group` display mode](/docs/content/navigation#display-modes), whether the group starts collapsed. Unset, it starts collapsed unless it holds the current page or is the only row at the top of the sidebar. |
|
|
36
38
|
| `display` | `"flat" \| "group" \| "page"` | Render mode for this group; overrides the global [`navigation.sidebar.display`](/docs/content/navigation#display-modes). |
|
|
37
39
|
| `directory` | `"card" \| "accordion" \| "none"` | List the group's pages below its `index` page's content. Nested folders inherit it. See [directory listings](/docs/content/navigation#directory-listings). |
|
|
38
40
|
| `pages` | `string[]` | Explicit order for the group's children, by slug. |
|
|
39
41
|
|
|
40
|
-
The `pages` array lists children by slug — the folder or file name with its numeric prefix and any parentheses stripped (so `01-quickstart.mdx` is `"quickstart"`). Each listed child takes its position in the array as its order (`0`, `1`, `2`, …). Children you leave out still appear, sorted by their own order: an `index` page stays first, a child with a `sidebar.order`, a numeric prefix, or its own `meta.ts` `order` sorts by that number among the listed ones, and a child with none of these goes after them. List every child when the array should be the whole order.
|
|
42
|
+
The `pages` array lists children by slug — the folder or file name with its numeric prefix and any parentheses stripped (so `01-quickstart.mdx` is `"quickstart"`). Each listed child takes its position in the array as its order (`0`, `1`, `2`, …). Children you leave out still appear, sorted by their own order: an `index` page stays first, a child with a `sidebar.order`, a numeric prefix, or its own `meta.ts` `order` sorts by that number among the listed ones, and a child with none of these goes after them. List every child when the array should be the whole order. An entry that names no page or folder in the group orders nothing, so Blume warns about it as `BLUME_META_UNKNOWN_PAGE`, at its line in `meta.ts`, and suggests the slug it most likely means.
|
|
41
43
|
|
|
42
44
|
The array orders pages among pages and groups among groups, but it doesn't interleave the two where loose pages list above groups: at the top of the sidebar (and of each [tab](/docs/content/navigation#tabs) section), and in any group with a [`flat`](/docs/content/navigation#display-modes) subgroup, whose header would otherwise seem to own the pages after it. There, `pages: ["advanced", "intro"]` still lists the `intro` page above the `advanced` group.
|
|
43
45
|
|
|
44
46
|
How groups render — flat headers, collapsible disclosures, or drill-in panels — defaults to the sidebar-wide `navigation.sidebar.display`; set `display` here to override it for this group alone. A folder's `index` page can also set it from frontmatter, which wins over `meta.ts` — see [per-group overrides](/docs/content/navigation#per-group-overrides).
|
|
45
47
|
|
|
48
|
+
## Generated groups
|
|
49
|
+
|
|
50
|
+
An [OpenAPI](/docs/references/openapi), [AsyncAPI](/docs/references/asyncapi), or [GraphQL](/docs/references/graphql) reference names and orders its tag groups from the spec. To change one, add a `meta.ts` in the folder the tag's pages publish under: with the reference at `/api`, `api/pets/meta.ts` in your content folder configures the **Pets** group. The fields it sets replace the generated ones, and the rest keep their generated values, so a `meta.ts` that sets only `title` keeps the tag's place in the spec's order.
|
|
51
|
+
|
|
46
52
|
## Computed meta
|
|
47
53
|
|
|
48
54
|
Because `meta.ts` is a real module, you can compute the meta — pass a function (sync or `async`) instead of an object to build it at scan time. Handy for ordering pages from an external source:
|