blume 2.0.3 → 2.1.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 -0
- package/CHANGELOG.md +142 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
- package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
- package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
- package/dist/cli/chunk-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
- package/dist/cli/chunk-313vnn40.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
- package/dist/cli/chunk-3x6x3pph.js.map +10 -0
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
- package/dist/cli/chunk-42t4jxdx.js.map +12 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
- package/dist/cli/chunk-54ztw1nj.js.map +10 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
- package/dist/cli/chunk-66w9j7p6.js +322 -0
- package/dist/cli/chunk-66w9j7p6.js.map +14 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
- package/dist/cli/chunk-7ppf1rva.js.map +10 -0
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
- package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
- package/dist/cli/chunk-cfyg47zg.js.map +10 -0
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
- package/dist/cli/chunk-e6atmn4h.js.map +36 -0
- package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
- package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
- package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
- package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
- package/dist/cli/chunk-ehweg4fr.js.map +218 -0
- package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
- package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
- package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
- package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
- package/dist/cli/chunk-gb420vvz.js.map +17 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
- package/dist/cli/chunk-hebn0tpx.js.map +14 -0
- package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
- package/dist/cli/chunk-htrwgabr.js.map +15 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
- package/dist/cli/chunk-j134vrp2.js +65 -0
- package/dist/cli/chunk-j134vrp2.js.map +10 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
- package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
- package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
- package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
- package/dist/cli/chunk-ncj7w596.js.map +35 -0
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
- package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
- package/dist/cli/chunk-nrns10mj.js.map +10 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
- package/dist/cli/chunk-t2m5j4pr.js +104 -0
- package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
- package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
- package/dist/cli/chunk-tphac74f.js +126 -0
- package/dist/cli/chunk-tphac74f.js.map +11 -0
- package/dist/cli/chunk-w1r4vase.js +18 -0
- package/dist/cli/chunk-w1r4vase.js.map +10 -0
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/index.js +31 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +26 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +9 -0
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +62 -0
- package/dist/types/components/content/api-page.d.ts +100 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +158 -0
- package/dist/types/components/openapi/security.d.ts +95 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +217 -23
- package/dist/types/core/data.d.ts +53 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +88 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +152 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +670 -56
- package/dist/types/core/sources/cache.d.ts +3 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
- package/dist/types/core/sources/contentful.d.ts +17 -1
- package/dist/types/core/sources/lexical.d.ts +5 -0
- package/dist/types/core/sources/normalize.d.ts +20 -1
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/sources/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +18 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +26 -1
- package/dist/types/deploy/redirects.d.ts +55 -11
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- package/dist/types/openapi/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +27 -10
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +16 -0
- package/dist/types/openapi/references.d.ts +30 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +119 -0
- package/dist/types/ratelimit/upstash.d.ts +46 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +89 -11
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +82 -6
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +144 -36
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +13 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/seo/metatags.d.ts +20 -0
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +54 -0
- package/dist/types/sources/shared.d.ts +3 -0
- package/dist/types/sources/strapi.d.ts +2 -0
- package/docs/01-quickstart.mdx +4 -2
- package/docs/02-deployment.mdx +71 -17
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +13 -2
- package/docs/advanced/skills.mdx +15 -1
- package/docs/cli/audit.mdx +51 -8
- package/docs/cli/doctor.mdx +5 -1
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +194 -38
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +8 -6
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +64 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +90 -0
- package/docs/configuration/search.mdx +63 -12
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +108 -2
- package/docs/content/frontmatter.mdx +80 -2
- package/docs/content/i18n.mdx +39 -4
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +32 -10
- package/docs/content/sources/contentful.mdx +35 -0
- package/docs/content/sources/custom.mdx +43 -0
- package/docs/content/sources/github-releases.mdx +39 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +31 -0
- package/docs/content/sources/remote-mdx.mdx +44 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +32 -0
- package/docs/content/syntax.mdx +69 -4
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +2 -2
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +2 -2
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +4 -2
- package/docs/references/graphql.mdx +14 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +148 -7
- package/docs/references/scalar.mdx +3 -1
- package/package.json +43 -8
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +7 -7
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +10 -7
- package/skills/blume-migrate/references/starlight.md +11 -8
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +103 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +76 -1
- package/src/ai/cors.ts +14 -3
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +36 -6
- package/src/ai/relative-links.ts +4 -38
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +210 -66
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +42 -4
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +9 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/templates.ts +406 -108
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +38 -3
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +19 -13
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +5 -0
- package/src/audit/types.ts +4 -1
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +12 -1
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +67 -28
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/index.ts +5 -0
- package/src/cli/init/scaffold.ts +3 -3
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +72 -30
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +66 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +103 -0
- package/src/components/content/api-page.ts +248 -0
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +136 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +318 -47
- package/src/components/layout/Search.astro +47 -19
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +126 -0
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +32 -0
- package/src/components/layout/search/typesense.ts +19 -3
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +184 -13
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +24 -5
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +7 -4
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +65 -9
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +24 -5
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +16 -3
- package/src/components/openapi/snippets.ts +873 -10
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/client-address.ts +19 -0
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +225 -23
- package/src/core/data.ts +46 -4
- package/src/core/diagnostics.ts +8 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +84 -2
- package/src/core/includes.ts +21 -4
- package/src/core/links.ts +63 -19
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +163 -16
- package/src/core/redirect-patterns.ts +520 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +339 -66
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/contentful-rich-text.ts +29 -6
- package/src/core/sources/contentful.ts +135 -25
- package/src/core/sources/filesystem.ts +26 -4
- package/src/core/sources/github-releases.ts +12 -1
- package/src/core/sources/lexical.ts +15 -10
- package/src/core/sources/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +228 -41
- package/src/core/sources/notion.ts +7 -1
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/read.ts +8 -3
- package/src/core/sources/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +19 -1
- package/src/core/ui-packs/ar.ts +44 -0
- package/src/core/ui-packs/bg.ts +46 -0
- package/src/core/ui-packs/bn.ts +44 -0
- package/src/core/ui-packs/ca.ts +47 -0
- package/src/core/ui-packs/cs.ts +45 -0
- package/src/core/ui-packs/da.ts +46 -0
- package/src/core/ui-packs/de.ts +47 -0
- package/src/core/ui-packs/el.ts +46 -0
- package/src/core/ui-packs/es.ts +47 -0
- package/src/core/ui-packs/fa.ts +46 -0
- package/src/core/ui-packs/fi.ts +46 -0
- package/src/core/ui-packs/fr.ts +47 -0
- package/src/core/ui-packs/he.ts +44 -0
- package/src/core/ui-packs/hi.ts +45 -0
- package/src/core/ui-packs/hr.ts +46 -0
- package/src/core/ui-packs/hu.ts +45 -0
- package/src/core/ui-packs/id.ts +46 -0
- package/src/core/ui-packs/it.ts +46 -0
- package/src/core/ui-packs/ja.ts +46 -0
- package/src/core/ui-packs/ko.ts +45 -0
- package/src/core/ui-packs/nl.ts +47 -0
- package/src/core/ui-packs/no.ts +45 -0
- package/src/core/ui-packs/pl.ts +46 -0
- package/src/core/ui-packs/pt-br.ts +47 -0
- package/src/core/ui-packs/pt.ts +46 -0
- package/src/core/ui-packs/ro.ts +46 -0
- package/src/core/ui-packs/ru.ts +46 -0
- package/src/core/ui-packs/sk.ts +45 -0
- package/src/core/ui-packs/sr.ts +46 -0
- package/src/core/ui-packs/sv.ts +45 -0
- package/src/core/ui-packs/th.ts +44 -0
- package/src/core/ui-packs/tr.ts +46 -0
- package/src/core/ui-packs/uk.ts +46 -0
- package/src/core/ui-packs/vi.ts +46 -0
- package/src/core/ui-packs/zh-tw.ts +44 -0
- package/src/core/ui-packs/zh.ts +44 -0
- package/src/core/variables.ts +103 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +79 -9
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +45 -9
- package/src/deploy/platforms/netlify.ts +35 -2
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +149 -17
- package/src/deploy/redirects.ts +151 -24
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +326 -102
- package/src/eval/agents.ts +18 -1
- package/src/eval/prompts.ts +6 -3
- package/src/eval/report.ts +34 -13
- package/src/eval/run.ts +5 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/relative-links.ts +3 -2
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +7 -6
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +72 -27
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +182 -4
- package/src/openapi/references.ts +64 -8
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +40 -15
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +247 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +60 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +20 -3
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +80 -8
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +23 -5
- package/src/registry/registry.ts +7 -0
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +191 -34
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +111 -10
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +76 -26
- package/src/seo/metatags.ts +67 -0
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/shared.ts +3 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +85 -6
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +31 -3
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
- package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
- package/dist/cli/chunk-35d4wj9f.js.map +0 -15
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-8ktnccpt.js.map +0 -10
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-b07cmahc.js +0 -145
- package/dist/cli/chunk-b07cmahc.js.map +0 -11
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-e04dxsz1.js +0 -39
- package/dist/cli/chunk-e04dxsz1.js.map +0 -10
- package/dist/cli/chunk-j85vccga.js.map +0 -36
- package/dist/cli/chunk-p3v96n38.js.map +0 -10
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
package/docs/02-deployment.mdx
CHANGED
|
@@ -16,7 +16,16 @@ sidebar:
|
|
|
16
16
|
| Output directory | `dist` |
|
|
17
17
|
| Node version | 22.12 or newer |
|
|
18
18
|
|
|
19
|
-
These settings work on Vercel, Netlify, Cloudflare Pages, GitHub Pages,
|
|
19
|
+
These settings work on Vercel, Netlify, Cloudflare Pages, GitHub Pages, or any bucket or CDN. Make sure `blume` is a dependency so the host can run the build.
|
|
20
|
+
|
|
21
|
+
Amazon S3 behind CloudFront, with a private bucket read through origin access control, needs two more pieces, because the S3 REST endpoint looks up each key exactly and serves each file with the type it was uploaded with:
|
|
22
|
+
|
|
23
|
+
- A CloudFront Function on viewer requests that maps each page URL to the `index.html` Blume writes for it: `/quickstart` to `/quickstart/index.html`, and `/` (or any path ending in `/`) to its `index.html`. Leave a path whose last segment has a dot (`/quickstart.md`, `/_astro/app.js`) unchanged, and keep the function off `/.well-known/*`, whose `api-catalog` has no extension. Without it, S3 answers `/quickstart` with a `403` or `404`.
|
|
24
|
+
- Uploads that set the types a guess from the file extension gets wrong or leaves without a charset: `text/markdown; charset=utf-8` for `.md` and `.mdx`, `text/plain; charset=utf-8` for `.txt`, and `application/linkset+json; profile="https://www.rfc-editor.org/info/rfc9727"` for `.well-known/api-catalog`. `dist/_headers` lists every rule your build needs.
|
|
25
|
+
|
|
26
|
+
The [S3 and CloudFront guide](/guides/s3-cloudfront-documentation-site) has a CloudFormation template with the function and a deploy script that uploads with these types.
|
|
27
|
+
|
|
28
|
+
On Cloudflare Workers, which serves a static build as static assets, set `"html_handling": "drop-trailing-slash"` under `assets` in your Wrangler config. Blume writes each page as `<route>/index.html` and links to it without a trailing slash, and Cloudflare's default (`auto-trailing-slash`) answers `/quickstart` with a `307` to `/quickstart/`. A [`cloudflare()` server build](#server-rendering) routes every page through its Worker, which serves `/quickstart` under either setting, so there it only matters when the build warns `Could not wire Accept: text/markdown negotiation` and the static layer serves the pages itself.
|
|
20
29
|
|
|
21
30
|
A static build includes:
|
|
22
31
|
|
|
@@ -40,10 +49,14 @@ deployment: {
|
|
|
40
49
|
}
|
|
41
50
|
```
|
|
42
51
|
|
|
43
|
-
On Vercel and Netlify, automatic detection prefers your stable production domain over per-deploy preview URLs, so the canonical origin stays put across deploys. Cloudflare Pages exposes only the current deployment's URL (`CF_PAGES_URL`), which changes with every deploy, so set `site` there.
|
|
52
|
+
On Vercel and Netlify, automatic detection prefers your stable production domain over per-deploy preview URLs, so the canonical origin stays put across deploys. Cloudflare Pages exposes only the current deployment's URL (`CF_PAGES_URL`), which changes with every deploy, so set `site` there. Cloudflare Workers exposes none, so set `site` on Workers too.
|
|
44
53
|
|
|
45
54
|
During `blume dev`, the site URL falls back to your local dev server (e.g. `http://localhost:4321`) when none is set, so site-gated features — Open Graph images, canonicals, the sitemap — work out of the box. Builds never use this fallback, so production output is never pointed at localhost.
|
|
46
55
|
|
|
56
|
+
### Monorepos
|
|
57
|
+
|
|
58
|
+
Deploy the docs workspace as its own project, with the host's root directory set to it (Vercel's **Root Directory**, Netlify's **Base directory**) and the settings above. On Vercel, leave **Include source files outside of the Root Directory in the Build Step** on, which is the default, whenever the docs read files outside their workspace: [component examples](/docs/content/components#component) or a workspace package they import, an `@source` path in `theme.css`, or a spec elsewhere in the repository. With it off, the build can't reach those files. The [monorepo guide](/guides/monorepo-documentation-site) walks through a pnpm and Turborepo setup.
|
|
59
|
+
|
|
47
60
|
## Preview locally
|
|
48
61
|
|
|
49
62
|
Before you ship, preview the production build exactly as a static host would serve it:
|
|
@@ -65,7 +78,7 @@ deployment: {
|
|
|
65
78
|
}
|
|
66
79
|
```
|
|
67
80
|
|
|
68
|
-
`base` (and `site`) are options of every host adapter too: `vercel({ base: "/docs" })`.
|
|
81
|
+
`base` (and `site`) are options of every host adapter too: `vercel({ base: "/docs" })`. `@astrojs/vercel` ignores the base, so a `vercel()` server build moves the static files to `.vercel/output/static/docs/` and the routes and redirects in `.vercel/output/config.json` under `/docs` itself.
|
|
69
82
|
|
|
70
83
|
Every page keeps its own path under the base, even in a content folder that shares the base's name: with `base: "/docs"`, `docs/setup.md` is served at `/docs/docs/setup`, and its canonical URL, sidebar link, and `llms.txt` entry point there. A root-relative link you write that already starts with the base is taken to include it and left as written, so link to that page with a relative link (`./docs/setup`) or its full path (`/docs/docs/setup`).
|
|
71
84
|
|
|
@@ -112,9 +125,9 @@ deployment: vercel({
|
|
|
112
125
|
| `vercel()` | `@astrojs/vercel` | Vercel — the most polished path |
|
|
113
126
|
| `netlify()` | `@astrojs/netlify` | Netlify Functions |
|
|
114
127
|
| `node()` | `@astrojs/node` | Self-hosted Node servers, containers |
|
|
115
|
-
| `cloudflare()` | `@astrojs/cloudflare` | Cloudflare Workers
|
|
128
|
+
| `cloudflare()` | `@astrojs/cloudflare` | Cloudflare Workers |
|
|
116
129
|
|
|
117
|
-
`vercel()` and `node()` ship with Blume — choosing one just works. `netlify()` and `cloudflare()` need their package installed in your project (e.g. `bun add -d @astrojs/netlify`). If it's missing, `blume build` stops with the install command for your package manager, `blume dev` warns, and [`blume doctor`](/docs/cli/doctor) reports it. With pnpm
|
|
130
|
+
`vercel()` and `node()` ship with Blume — choosing one just works. `netlify()` and `cloudflare()` need their package installed in your project (e.g. `bun add -d @astrojs/netlify`). If it's missing, `blume build` stops with the install command for your package manager, `blume dev` warns, and [`blume doctor`](/docs/cli/doctor) reports it. With pnpm, also approve the build scripts those packages bring under `allowBuilds` in `pnpm-workspace.yaml`, beside the `esbuild` entry `blume init` writes: `sharp` for Netlify, whose adapter pulls in its own copy, and `workerd` for Cloudflare. pnpm 11 and later stop the install with `ERR_PNPM_IGNORED_BUILDS` until you approve them; pnpm 10 skips the scripts with a warning. `allowBuilds` needs pnpm 10.26 or later.
|
|
118
131
|
|
|
119
132
|
Naming an adapter switches the build to server output. To keep a static build on that host — with its site detection and the platform files it reads — pass `output: "static"`:
|
|
120
133
|
|
|
@@ -122,9 +135,9 @@ Naming an adapter switches the build to server output. To keep a static build on
|
|
|
122
135
|
deployment: netlify({ output: "static" }),
|
|
123
136
|
```
|
|
124
137
|
|
|
125
|
-
A server build includes everything a static build does, plus any Astro endpoints or middleware you add. The `node()` adapter produces a standalone server you can run directly with `node dist/server/entry.mjs`. It listens on `localhost:4321` unless you set the `HOST` and `PORT` environment variables when you start it (`HOST=0.0.0.0 PORT=8080 node dist/server/entry.mjs`); `host` and `port` passed to `node()` have no effect, because `@astrojs/node` replaces them with Astro's own server settings. The server resolves its packages through links into your project's `node_modules`, so deploy the project with its installed dependencies, not `dist/` alone. When the site publishes discovery files, serves images a content source downloaded, or configures redirects, Blume puts a small wrapper in front of Astro's entry (moved to `astro-entry.mjs` beside it). It sends the `.well-known` discovery files with their media types and CORS headers and downloaded SVGs sandboxed, which the standalone server's static handler can't do on its own, and answers each redirect with its configured status.
|
|
138
|
+
A server build includes everything a static build does, plus any Astro endpoints or middleware you add. The `node()` adapter produces a standalone server you can run directly with `node dist/server/entry.mjs`. It listens on `localhost:4321` unless you set the `HOST` and `PORT` environment variables when you start it (`HOST=0.0.0.0 PORT=8080 node dist/server/entry.mjs`); `host` and `port` passed to `node()` have no effect, because `@astrojs/node` replaces them with Astro's own server settings. Behind a reverse proxy, set `allowedDomains` so the [rate limit](/docs/configuration/rate-limiting#behind-a-reverse-proxy) counts each reader apart. The server resolves its packages through links into your project's `node_modules`, so deploy the project with its installed dependencies, not `dist/` alone. When the site publishes discovery files, serves images a content source downloaded, or configures redirects, Blume puts a small wrapper in front of Astro's entry (moved to `astro-entry.mjs` beside it). It sends the `.well-known` discovery files with their media types and CORS headers and downloaded SVGs sandboxed, which the standalone server's static handler can't do on its own, and answers each redirect with its configured status.
|
|
126
139
|
|
|
127
|
-
A `cloudflare()` server build deploys with `npx wrangler deploy` from the project root after `blume build`: Blume writes the redirected Wrangler config to `.wrangler/deploy/` (and adds `.wrangler/` to `.gitignore`), and names the Worker after your project — the `package.json` `name`, else the site's hostname, else the folder — unless a `wrangler.jsonc` of your own at the project root sets `name`.
|
|
140
|
+
A `cloudflare()` server build runs on Cloudflare Workers only, since `@astrojs/cloudflare` dropped Cloudflare Pages in version 13; a static build doesn't load the package, so its `dist/` still deploys to Pages. The server build deploys with `npx wrangler deploy` from the project root after `blume build`: Blume writes the redirected Wrangler config to `.wrangler/deploy/` (and adds `.wrangler/` to `.gitignore`), and names the Worker after your project — the `package.json` `name`, else the site's hostname, else the folder — unless a `wrangler.jsonc` of your own at the project root sets `name`.
|
|
128
141
|
|
|
129
142
|
On Vercel and Cloudflare, a server build also turns on [`Accept: text/markdown` content negotiation](/docs/discoverability/markdown#content-negotiation), so an agent requesting any content page with that header receives its raw-Markdown mirror at the same URL. On Vercel, Blume splices header-conditional rewrites into the deploy's routing config; on Cloudflare, it generates a small Worker in front of the Astro one and points `assets.run_worker_first` at every path except the fingerprinted build assets and the raw `.md`, `.txt`, `.json`, and `.well-known` files, since the platform would otherwise serve the prerendered pages — and its `404.html` for a URL no page backs — before any server code runs; those exempted files keep their zero-Worker fast path. That Worker also answers the prerendered per-page JSON documents (`/api/docs/pages/{route}.json`) from the asset binding when a request for one reaches it, because Astro would otherwise route it to the `/api/` catch-all.
|
|
130
143
|
|
|
@@ -136,6 +149,23 @@ On Vercel and Cloudflare, a server build also turns on [`Accept: text/markdown`
|
|
|
136
149
|
Server features have their own configuration — for example, the assistant needs a model API key. See the [assistant guide](/docs/configuration/assistant) for setup.
|
|
137
150
|
:::
|
|
138
151
|
|
|
152
|
+
## Private docs
|
|
153
|
+
|
|
154
|
+
Blume has no sign-in of its own. A static build is plain files, and anyone who can reach the host can fetch anything in `dist/`. To keep a site private, turn on your host's access protection, which checks every request before a file is served:
|
|
155
|
+
|
|
156
|
+
- **Vercel**: [Deployment Protection](https://vercel.com/docs/deployment-protection) with the **All Deployments** scope, so production is covered and not only previews. Vercel Authentication lets in members of your Vercel team; Password Protection lets in anyone with a shared password, on paid plans.
|
|
157
|
+
- **Netlify**: [password protection](https://docs.netlify.com/manage/security/secure-access-to-sites/password-protection/) on all deploys, with a shared password, or with team login on Enterprise plans.
|
|
158
|
+
- **Cloudflare**: [Cloudflare Access](https://developers.cloudflare.com/workers/configuration/cloudflare-access/) on the Worker that serves the site (**Workers & Pages**, then your Worker, then **Access**), which covers every domain it answers on. Choose who can sign in by email address, email domain, or Cloudflare account membership.
|
|
159
|
+
- **GitHub Pages**: publish the site privately from an organization on GitHub Enterprise Cloud, and only people with read access to the repository can view it.
|
|
160
|
+
- **Your own server**: put authentication in front of `dist/`, such as nginx's `auth_basic` or an identity-aware proxy.
|
|
161
|
+
|
|
162
|
+
Host protection works the same for [server builds](#server-rendering). It covers the whole site: to keep some pages public, publish them as a separate site.
|
|
163
|
+
|
|
164
|
+
Everything Blume writes to `dist/` sits behind the protection, including pages, the search index, the `.md` copies, `llms.txt`, and Open Graph images. A few features reach outside it:
|
|
165
|
+
|
|
166
|
+
- A hosted [search provider](/docs/configuration/search) (Algolia, Orama Cloud, Typesense, or Mixedbread) keeps its own copy of your content on that service. The built-in Orama, FlexSearch, and Pagefind indexes are files in `dist/`, so they stay private.
|
|
167
|
+
- Services outside the protection can't read your pages. **Open in chat** hands ChatGPT or Claude a link it can't open, link previews in Slack or X can't show your Open Graph cards, and agents can't read `llms.txt` or the MCP server. Set `ai.openInChat: false` to hide the chat actions.
|
|
168
|
+
|
|
139
169
|
## Redirects
|
|
140
170
|
|
|
141
171
|
Map old URLs to new ones in `blume.config.ts`:
|
|
@@ -144,37 +174,61 @@ Map old URLs to new ones in `blume.config.ts`:
|
|
|
144
174
|
redirects: [{ from: "/old", to: "/new", status: 301 }],
|
|
145
175
|
```
|
|
146
176
|
|
|
147
|
-
`status` accepts `301`, `302`, `307`, or `308` (default `301`). Server builds answer redirects at request time with the configured status
|
|
177
|
+
`status` accepts `301`, `302`, `307`, or `308` (default `301`). Server builds answer redirects at request time with the configured status, and so does `blume dev`. Static builds emit redirect pages **and** the platform files your host reads, so it issues a real HTTP redirect: `_redirects` for `netlify()` and `cloudflare()`, `vercel.json` for `vercel()`, and — when no host is named — both of those plus `blume-redirects.json`, a structured manifest for anything else (nginx/Apache rules, an edge worker). A `_redirects` or `vercel.json` you ship in `public/` is left untouched.
|
|
178
|
+
|
|
179
|
+
A redirect that moves one page to another moves the page's [raw Markdown](/docs/discoverability/markdown#raw-markdown) with it: `/old.md` and `/old.mdx` redirect to `/new.md` and `/new.mdx` with the same status, in `blume dev` and every build.
|
|
148
180
|
|
|
149
181
|
Two hosts need more than the file:
|
|
150
182
|
|
|
151
183
|
- **Netlify** serves a file that exists ahead of a redirect rule unless the rule is forced, and a static build has a redirect page at every `from`. The `_redirects` for `netlify()` forces its rules (`/old /new 301!`). Cloudflare rejects that flag, so the file a build for no named host writes leaves it off, and on Netlify that build answers with the redirect page instead; name the host with `netlify({ output: "static" })` to get the HTTP redirect.
|
|
152
184
|
- **Vercel** reads `vercel.json` from the project's root directory, never from the output directory, so the copy in `dist/` applies only when you deploy that folder itself with the Vercel CLI (`vercel deploy dist`). A Git-connected project never reads it: it serves the redirect pages and none of the headers from [Content types](#content-types). Copy the `redirects` and `headers` from `dist/vercel.json` into the `vercel.json` in your project's root directory, or use `vercel()` for a server build, whose routing config carries the redirects and the discovery headers.
|
|
153
185
|
|
|
154
|
-
:::note
|
|
155
|
-
`from` and `to` are exact paths — a `:param` segment or `*` wildcard (e.g. `/blog/:slug` or `/old/*`) fails config validation, since hosts disagree on patterns. If you need pattern-based rules, handle them in an infrastructure file like `vercel.json` (which supports wildcard `source` patterns) or your host's redirect config instead. A `vercel.json` you ship in `public/` is preserved as-is.
|
|
156
|
-
:::
|
|
157
|
-
|
|
158
186
|
:::note
|
|
159
187
|
Write both `from` and `to` as if mounted at root, starting with `/` (`to` can also be a full `https://` URL) — under [`base`](#subpath-deploys) and [`basePath`](#mount-the-docs-under-a-path) alike, Blume rewrites both sides for you, so a redirect lands inside the base. A `to` that names a file in `public/` (`/files/guide.pdf`) gains `base` but not `basePath`, since that's where the file is served. A base you've already written into `to` by hand is preserved rather than doubled.
|
|
160
188
|
:::
|
|
161
189
|
|
|
190
|
+
### Pattern redirects
|
|
191
|
+
|
|
192
|
+
A `from` can cover many paths at once, written the way Mintlify and `vercel.json` write them:
|
|
193
|
+
|
|
194
|
+
```ts blume.config.ts
|
|
195
|
+
redirects: [
|
|
196
|
+
{ from: "/beta/:slug*", to: "/v2/:slug*" },
|
|
197
|
+
{ from: "/blog/:slug", to: "/articles/:slug" },
|
|
198
|
+
{ from: "/articles/concepts-*", to: "/concepts" },
|
|
199
|
+
{ from: "/old/article-*", to: "/new/article-*" },
|
|
200
|
+
],
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
- `:name` matches one whole segment: `/blog/:slug` covers `/blog/hello`, not `/blog/a/b`.
|
|
204
|
+
- `:name*` as the last segment matches the rest of the path, any number of segments: `/beta/:slug*` sends `/beta/guides/setup` to `/v2/guides/setup`, and `/beta` itself to `/v2`. A last segment of `*` does the same.
|
|
205
|
+
- `*` at the end of a segment matches the rest of the path from there: `/articles/concepts-*` covers `/articles/concepts-overview`.
|
|
206
|
+
|
|
207
|
+
`to` reads a capture by name, as a whole segment (`/:slug*`, `/:slug`), or a `*` for what the `*` in `from` matched (`:splat`, the way `_redirects` spells it, reads it too). A `to` that reads no capture sends every path the pattern covers to one page. An exact redirect wins over a pattern that covers the same path, and patterns are tried in the order you list them.
|
|
208
|
+
|
|
209
|
+
Each host gets the patterns in its own syntax: splats in `_redirects`, `path-to-regexp` sources in `vercel.json`, and the routing config of a `vercel()` or `netlify()` server build. The `node()` and `cloudflare()` servers match them themselves, and so does `blume dev`. A static build writes no redirect page for a pattern, since it would need one for every path the pattern covers, so a host that reads none of these files (GitHub Pages, say) applies only the exact redirects; `blume-redirects.json` lists patterns as you wrote them.
|
|
210
|
+
|
|
211
|
+
A pattern can't also match a page: hosts disagree on which of the two answers, so the build stops with `BLUME_REDIRECT_MATCHES_PAGE`, naming the page. Narrow the pattern to the paths that moved. An exact redirect from a page's own URL answers the same way on every host, taking the URL over so the page never publishes, so the same code is a warning there: delete the page if it moved, or drop the redirect.
|
|
212
|
+
|
|
162
213
|
## Content types
|
|
163
214
|
|
|
164
215
|
Where the host reads one, a build also emits a `_headers` file that pins `charset=utf-8` onto the raw AI-ready endpoints — `/<route>.md`, `/<route>.mdx`, and the `.txt` files (`llms.txt`, `llms-full.txt`). Those responses are valid UTF-8, but many static hosts serve them as `text/markdown` / `text/plain` with **no** charset, and browsers then fall back to Windows-1252 — so non-ASCII docs (Japanese, accented Latin, …) render as mojibake when the raw URL is opened directly. HTML pages are unaffected because they carry `<meta charset>`. Netlify reads `_headers` on a static deploy and Cloudflare (Pages, and Workers static assets) on both static and server builds, so those adapters and an unnamed static host get the file; Vercel (whose headers ride the routing config) and Node (whose server ignores the file) don't. A Netlify server build writes the same rules into the `headers` of its Frameworks API config (`.netlify/v1/config.json`) instead. A static Vercel build writes the same rules into `dist/vercel.json` instead, which a Git-connected project doesn't read (see [Redirects](#redirects)). A `_headers` you ship in `public/` is left untouched.
|
|
165
216
|
|
|
166
217
|
## Environment variables
|
|
167
218
|
|
|
168
|
-
When a feature needs a
|
|
219
|
+
When a feature needs a secret, Blume warns at `blume dev`/`build` if it's missing — so the problem surfaces early instead of at the first request:
|
|
169
220
|
|
|
170
221
|
| Feature | Variable |
|
|
171
222
|
| --- | --- |
|
|
172
223
|
| Assistant (AI Gateway) | `AI_GATEWAY_API_KEY` (or Vercel OIDC) |
|
|
173
|
-
| Assistant (other adapters) | the adapter's default key env var (`OPENROUTER_API_KEY`, `LLMGATEWAY_API_KEY`, `INKEEP_API_KEY`), or the `apiKeyEnv` you passed it |
|
|
224
|
+
| Assistant (other adapters) | the adapter's default key env var (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`, `LLMGATEWAY_API_KEY`, `INKEEP_API_KEY`), or the `apiKeyEnv` you passed it |
|
|
225
|
+
| [Assistant bot protection](/docs/configuration/assistant#bot-protection) | `TURNSTILE_SECRET_KEY` (`turnstile()`), `HCAPTCHA_SECRET_KEY` (`hcaptcha()`) |
|
|
226
|
+
| [Rate limiting](/docs/configuration/rate-limiting) (`upstash()`) | `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` |
|
|
174
227
|
| Mixedbread search | `MIXEDBREAD_API_KEY` |
|
|
175
|
-
| [
|
|
228
|
+
| [Narration](/docs/configuration/narration) (generated voices) | `AI_GATEWAY_API_KEY` (or Vercel OIDC), or the `apiKeyEnv` you passed `gateway()` |
|
|
229
|
+
| [Content sources](/docs/content/sources) | `NOTION_TOKEN` (`notion()`), `SANITY_TOKEN` (`sanity()`), `CONTENTFUL_ACCESS_TOKEN` (`contentful()`, plus `CONTENTFUL_PREVIEW_TOKEN` for `--preview`, which fails without it), `PAYLOAD_API_KEY` (`payload()`), `STRAPI_API_TOKEN` (`strapi()`), `GITHUB_TOKEN` (`githubReleases()`, and `mdxRemote()` reading from GitHub) |
|
|
176
230
|
|
|
177
|
-
Set them in `.env.local` for local dev and in your host's environment for production. A content source reads its token when it fetches, during `blume dev` and `blume build`, so set
|
|
231
|
+
Set them in `.env.local` for local dev and in your host's environment for production. A content source reads its token when it fetches, during `blume dev` and `blume build`, and narration reads its key during `blume build`, so set those where your site builds. Build-time secrets for search-index sync (`ALGOLIA_ADMIN_API_KEY`, `ORAMA_PRIVATE_API_KEY`, `TYPESENSE_ADMIN_API_KEY`) are checked by the sync step itself: when one is unset, the build warns and skips the sync, and when it's set, a failed sync [fails the build](/docs/configuration/search#adapters). The [GitHub info](/docs/content/components#github-info) card also sends `GITHUB_TOKEN`, when it's set, to lift GitHub's API rate limit.
|
|
178
232
|
|
|
179
233
|
## Build cache
|
|
180
234
|
|
|
@@ -186,7 +240,7 @@ Blume keeps two caches a build can reuse. Astro's and Vite's caches live under `
|
|
|
186
240
|
- **GitHub Actions** and other runners you manage keep nothing unless you cache the directory yourself:
|
|
187
241
|
|
|
188
242
|
```yaml
|
|
189
|
-
- uses: actions/cache@
|
|
243
|
+
- uses: actions/cache@v6
|
|
190
244
|
with:
|
|
191
245
|
path: node_modules/.cache/blume/og
|
|
192
246
|
key: blume-og-${{ runner.os }}-${{ hashFiles('**/bun.lock', '**/package-lock.json', '**/pnpm-lock.yaml') }}
|
package/docs/03-upgrading.mdx
CHANGED
|
@@ -6,7 +6,7 @@ sidebar:
|
|
|
6
6
|
order: 2.5
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
Blume 2 changes configuration, not content: your Markdown and MDX pages need no edits
|
|
9
|
+
Blume 2 changes configuration, not content: your Markdown and MDX pages need no edits (see [Frontmatter](#frontmatter) for one field that now does something). Settings that used to be a named string or a keyed block — the search provider, the deployment target, content sources, API references, analytics, and the assistant's model backend — are now **adapters** you import from a `blume/*` subpath and call. Ask AI is renamed the assistant, so `ai.ask` becomes `ai.assistant`. The machine-readable settings move from `ai` to a new `agents` key, and `components.ts` overrides are checked before the build. A zero-config site, or one that sets none of these, only needs the version bump.
|
|
10
10
|
|
|
11
11
|
## Upgrade with one command
|
|
12
12
|
|
|
@@ -87,7 +87,7 @@ export default defineConfig({
|
|
|
87
87
|
|
|
88
88
|
- `netlify()`, `cloudflare()`, and `node()` work the same way. Naming a host adapter switches to server output; pass `output: "static"` to keep a static build with that host's platform files.
|
|
89
89
|
- A config that only sets `site` or `base` stays as it is: `deployment: { site, base }` is still the static form.
|
|
90
|
-
- `redirects`
|
|
90
|
+
- `redirects` read `:name` segments and a trailing `*` as patterns, matched the same way on every host (see [Pattern redirects](/docs/deployment#pattern-redirects)). Blume 1 never supported patterns and handed them to each host as written, so check any `from` or `to` that holds one.
|
|
91
91
|
- The `--adapter`, `--output`, and `--base` flags on `blume build` are gone, and passing one stops the build with an error naming the `deployment` setting that replaces it. Set the adapter in `blume.config.ts`, and name it explicitly: server output is no longer inferred from the platform's environment.
|
|
92
92
|
|
|
93
93
|
See [Deployment](/docs/deployment) for each adapter's options.
|
|
@@ -239,7 +239,7 @@ export default defineConfig({
|
|
|
239
239
|
|
|
240
240
|
</CodeGroup>
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
A 1.x `provider` name maps onto `gateway()`, `openrouter()`, `llmgateway()`, or `inkeep()`, and `openai-compatible` onto `openai({ baseUrl, name, model, apiKeyEnv })`; the [adapter list](/docs/configuration/assistant#adapters) has the rest. `model`, `apiKeyEnv`, `baseUrl`, `headers`, and `reasoning` move into the adapter; `enabled`, `instructions`, `retrieval`, `suggestions`, `cors`, and `endpoint` move to `ai.assistant` unchanged. Leaving `provider` unset still uses the AI Gateway.
|
|
243
243
|
|
|
244
244
|
The rename reaches every name that said Ask AI:
|
|
245
245
|
|
|
@@ -290,7 +290,7 @@ export default defineConfig({
|
|
|
290
290
|
|
|
291
291
|
## Frontmatter
|
|
292
292
|
|
|
293
|
-
|
|
293
|
+
Pages keep their frontmatter. One field changes what it does: `search.boost`. Blume 1 accepted it, but search never read it, so a page ranked the same without it. It now multiplies the page's search relevance (see [Ranking](/docs/configuration/search#ranking)). Check any page that sets it: a boost you added and forgot now moves the page up.
|
|
294
294
|
|
|
295
295
|
## Component overrides
|
|
296
296
|
|
package/docs/04-migrating.mdx
CHANGED
|
@@ -43,7 +43,7 @@ The agent follows the playbook's workflow from the source's config to a passing
|
|
|
43
43
|
5. Points your `package.json` scripts at `blume dev` and `blume build`, and swaps the old framework's dependencies for `blume`.
|
|
44
44
|
6. Runs `blume build` and `blume validate` until both pass.
|
|
45
45
|
|
|
46
|
-
It finishes with a summary of what it migrated, dropped, or approximated, such as footer links or
|
|
46
|
+
It finishes with a summary of what it migrated, dropped, or approximated, such as footer links or navbar buttons with no Blume equivalent, so you can decide what to do with each.
|
|
47
47
|
|
|
48
48
|
## Other agents
|
|
49
49
|
|
|
@@ -62,13 +62,24 @@ Once you have at least one `type: changelog` entry, Blume generates a **`/change
|
|
|
62
62
|
- The date follows the configured [`dateFormat`](/docs/configuration#date-format), minus the year the row's group already shows.
|
|
63
63
|
- Drafts and `sidebar.hidden` entries are skipped.
|
|
64
64
|
|
|
65
|
+
The page is headed **Changelog** (in English), with a one-line description below. Set your own with `changelog` in your config; they also become the page's `<title>`, meta description, and OG card, and the top of its Markdown mirror at `/changelog.md`:
|
|
66
|
+
|
|
67
|
+
```ts blume.config.ts
|
|
68
|
+
changelog: {
|
|
69
|
+
title: "Release notes",
|
|
70
|
+
description: "Every Acme SDK release, newest first.",
|
|
71
|
+
},
|
|
72
|
+
```
|
|
73
|
+
|
|
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
|
+
|
|
65
76
|
The page appears only when nothing already occupies the `/changelog` route. To replace it with your own design, 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";`.
|
|
66
77
|
|
|
67
78
|
A header [tab](/docs/content/navigation#tabs) pointing at `/changelog` opens this index — no `href` needed.
|
|
68
79
|
|
|
69
80
|
## From GitHub Releases
|
|
70
81
|
|
|
71
|
-
Rather than authoring entries by hand, point the built-in [`githubReleases()` source](/docs/content/sources
|
|
82
|
+
Rather than authoring entries by hand, point the built-in [`githubReleases()` source](/docs/content/sources/github-releases) at a repo and every release becomes a `type: changelog` entry — the same timeline and feed, fed straight from the releases you already publish. Blume's own [changelog](/changelog) is built this way:
|
|
72
83
|
|
|
73
84
|
```ts blume.config.ts
|
|
74
85
|
import { filesystem, githubReleases } from "blume/sources";
|
|
@@ -85,7 +96,7 @@ content: {
|
|
|
85
96
|
}
|
|
86
97
|
```
|
|
87
98
|
|
|
88
|
-
The release name becomes the title, its tag becomes `changelog.version`, and its published date sorts the timeline. Each release page also gets a unique meta description summarized from its notes — markdown stripped, section headings and changeset commit-hash prefixes dropped, trimmed to the search-snippet length [`blume audit`](/docs/cli/audit) checks for — instead of falling back to the site description. A private repo authenticates with the `GITHUB_TOKEN` environment variable. See [
|
|
99
|
+
The release name becomes the title, its tag becomes `changelog.version`, and its published date sorts the timeline. Each release page also gets a unique meta description summarized from its notes — markdown stripped, section headings and changeset commit-hash prefixes dropped, trimmed to the search-snippet length [`blume audit`](/docs/cli/audit) checks for — instead of falling back to the site description. A private repo authenticates with the `GITHUB_TOKEN` environment variable. See [GitHub Releases](/docs/content/sources/github-releases) for every option.
|
|
89
100
|
|
|
90
101
|
## The RSS feed
|
|
91
102
|
|
package/docs/advanced/skills.mdx
CHANGED
|
@@ -23,7 +23,7 @@ npx skills add haydenbleasel/blume --skill blume-migrate
|
|
|
23
23
|
|
|
24
24
|
## Self-updating docs
|
|
25
25
|
|
|
26
|
-
`blume-update-docs` keeps your docs in sync with the product they document. On each run — typically from a schedule you configure in your agent runner — it audits recently merged PRs, changelogs, config schemas, and CLI help against the docs content, updates only pages that are factually stale (feature-flagged work is ignored), verifies with `blume build`, and opens or updates a `blume/*` pull request. If nothing drifted, it reports a clean no-op instead of opening a noisy PR.
|
|
26
|
+
`blume-update-docs` keeps your docs in sync with the product they document. On each run — typically from a schedule you configure in your agent runner — it audits recently merged PRs, changelogs, config schemas, and CLI help against the docs content, updates only pages that are factually stale (feature-flagged work is ignored), verifies with `blume build` and `blume validate`, and opens or updates a `blume/*` pull request. If nothing drifted, it reports a clean no-op instead of opening a noisy PR.
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
npx skills add haydenbleasel/blume --skill blume-update-docs
|
|
@@ -34,3 +34,17 @@ Blume doesn't host the automation — wire the skill into a scheduled task in Cl
|
|
|
34
34
|
```text
|
|
35
35
|
Use the blume-update-docs skill. Review the PRs merged within the last 7 days and compare them to the docs content. Ignore work behind feature flags. If docs need updates, make them, verify the docs build, and open a blume/* PR. If not, report what you checked and do not open a PR.
|
|
36
36
|
```
|
|
37
|
+
|
|
38
|
+
## Writing your site's skill
|
|
39
|
+
|
|
40
|
+
`blume-write-skill` writes the [agent skill for your own docs](/docs/discoverability/agent-discovery#your-sites-skill): one `SKILL.md`, grounded in the docs, that teaches a coding agent to use your product — setup, core concepts, common tasks, and gotchas — with each topic linked to its page. It takes the place of the page map Blume generates at `/skill.md`. The quickest way to run it is `blume skill`, which works out where the skill goes and opens Codex or Claude Code on the copy bundled in the package:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
blume skill --claude # or --codex
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
To use it from another agent, install it:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npx skills add haydenbleasel/blume --skill blume-write-skill
|
|
50
|
+
```
|
package/docs/cli/audit.mdx
CHANGED
|
@@ -25,8 +25,9 @@ Findings are grouped by check rather than listed per page, so the report reads a
|
|
|
25
25
|
## Flags
|
|
26
26
|
|
|
27
27
|
- `--fail-on error|warning|info` — the CI gate: exit non-zero at this severity or above. Defaults to `error`; `--strict` is an alias for `--fail-on warning`.
|
|
28
|
-
- `--url <origin>` — also probe a live deployment for status codes, response headers, and
|
|
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
|
+
- `--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.
|
|
30
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
32
|
- `--list-checks` — print every check the audit can report, then exit.
|
|
32
33
|
- `--verbose` — list every affected page with each finding's full detail, instead of the first few.
|
|
@@ -44,14 +45,18 @@ blume audit --fail-on warning # also fails on warnings
|
|
|
44
45
|
|
|
45
46
|
## Checking a live deployment
|
|
46
47
|
|
|
47
|
-
Some things only the real server can tell you: whether a page that exists in `dist/` actually 404s behind a bad rewrite, whether responses are compressed,
|
|
48
|
+
Some things only the real server can tell you: whether a page that exists in `dist/` actually 404s behind a bad rewrite, whether responses are compressed, whether an `X-Robots-Tag` header is quietly deindexing a page whose HTML looks perfectly fine, and whether each old URL in [`redirects`](/docs/deployment#redirects) really redirects where you configured it. Point the audit at a deployment to add those checks:
|
|
48
49
|
|
|
49
50
|
```bash
|
|
50
51
|
blume audit --url https://docs.example.com
|
|
51
52
|
blume audit --url https://docs.example.com --external # also probe outbound links
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
These requests go out as a plain HTTP client, not as a crawler: the audit doesn't send Googlebot's or an AI crawler's user agent, since a host's bot protection can block a client pretending to be one. A firewall or CDN rule that treats crawlers differently isn't exercised, so check it with the crawler's own tools, such as Google Search Console's URL Inspection.
|
|
56
|
+
|
|
57
|
+
The audit requests every exact redirect's old URL (a pattern names no single URL to request). One that 404s is an error. One that answers 200 is a warning: a host that doesn't read the redirect file the build wrote serves the build's meta-refresh page there instead of an HTTP redirect, which readers follow but crawlers may not. See [Redirects](/docs/deployment#redirects) for what each host reads.
|
|
58
|
+
|
|
59
|
+
Outbound links are graded rather than flatly failed: a 404 or 410, or a host name that doesn't resolve, is a broken link you can fix, while any other error status (a 401 or 403 from a site that turns bots away, a 429, a 5xx), a refused connection, or a timeout is usually rate limiting or someone else's outage and is reported as a warning. Leave out URLs the audit can't check from where it runs, like a placeholder domain or a local server, with `--ignore`.
|
|
55
60
|
|
|
56
61
|
## Fixing the findings with an agent
|
|
57
62
|
|
|
@@ -69,15 +74,16 @@ This writes the complete JSON report — every affected page, not the terminal's
|
|
|
69
74
|
|
|
70
75
|
The check set is deliberately narrower than a general-purpose SEO crawler's. Much of what such a crawler reports cannot happen to a Blume site — it never emits `rel=nofollow`, and Vite's content-hashed bundles are never missing or redirecting — and reporting those as permanent zeroes would just teach you to ignore the report.
|
|
71
76
|
|
|
72
|
-
|
|
77
|
+
Limits worth stating plainly:
|
|
73
78
|
|
|
74
79
|
- **Structured data** is validated for well-formedness (valid JSON, a `@context`, a `@type` on every node). Blume does not validate against the full schema.org vocabulary or Google's rich-results rules.
|
|
80
|
+
- **Contrast** is checked for the colors your theme config sets, not element by element. The audit doesn't render pages, so a color you write by hand in MDX or `theme.css` isn't measured.
|
|
75
81
|
- **Core Web Vitals** are not checked. They need a real browser, and a flag that quietly measured nothing would be worse than not having one — so `blume audit` reports the layout-shift causes it _can_ see offline (images with no `width`/`height`, oversized assets) and leaves the rest alone for now.
|
|
76
82
|
|
|
77
83
|
Anything the audit did not run is reported as skipped rather than silently passing:
|
|
78
84
|
|
|
79
85
|
```
|
|
80
|
-
⊘ network skipped — pass --url <origin> (
|
|
86
|
+
⊘ network skipped — pass --url <origin> (12 checks)
|
|
81
87
|
⊘ external skipped — pass --external (2 checks)
|
|
82
88
|
```
|
|
83
89
|
|
|
@@ -87,6 +93,7 @@ Every check `blume audit` can report, grouped by category, with its default seve
|
|
|
87
93
|
|
|
88
94
|
| Category | Key |
|
|
89
95
|
| -------------------- | ----------------- |
|
|
96
|
+
| Accessibility | `accessibility` |
|
|
90
97
|
| Content | `content` |
|
|
91
98
|
| Duplicates | `duplicates` |
|
|
92
99
|
| Indexability | `indexability` |
|
|
@@ -193,7 +200,7 @@ Fix: Give each page a distinct `description`.
|
|
|
193
200
|
|
|
194
201
|
`BLUME_AUDIT_DUPLICATE_CONTENT` · warning · from the built HTML
|
|
195
202
|
|
|
196
|
-
Fix: Merge the pages, or
|
|
203
|
+
Fix: Merge the pages, or point `seo.canonical` on all but one at the page to index.
|
|
197
204
|
|
|
198
205
|
### Indexability
|
|
199
206
|
|
|
@@ -271,6 +278,8 @@ Fix: Remove the X-Robots-Tag header, or align it with the page's robots meta.
|
|
|
271
278
|
|
|
272
279
|
Fix: Fix the link target, or create the page it points at.
|
|
273
280
|
|
|
281
|
+
Under [`deployment.base`](/docs/deployment#subpath-deploys), a root-relative link without the base is reported here, since the host serves nothing of this build there. A full URL on the same host outside the base isn't: that's how a page links to another app the host serves beside the docs.
|
|
282
|
+
|
|
274
283
|
#### Page has links to a redirect [#link-to-redirect]
|
|
275
284
|
|
|
276
285
|
`BLUME_AUDIT_LINK_TO_REDIRECT` · warning · from the built HTML
|
|
@@ -343,7 +352,7 @@ Fix: Use a real redirect in `blume.config.ts` instead of a meta refresh.
|
|
|
343
352
|
|
|
344
353
|
`BLUME_AUDIT_REDIRECT_SOURCE_IS_PAGE` · error · from the built HTML
|
|
345
354
|
|
|
346
|
-
Fix: Remove the redirect, or delete the page it shadows —
|
|
355
|
+
Fix: Remove the redirect, or delete the page it shadows — a path can't be both, and which one readers get depends on the host.
|
|
347
356
|
|
|
348
357
|
#### HTTPS to HTTP redirect [#redirect-to-http]
|
|
349
358
|
|
|
@@ -351,6 +360,14 @@ Fix: Remove the redirect, or delete the page it shadows — the page wins and th
|
|
|
351
360
|
|
|
352
361
|
Fix: Redirect to the HTTPS URL.
|
|
353
362
|
|
|
363
|
+
#### Live site doesn't redirect as configured [#redirect-not-served]
|
|
364
|
+
|
|
365
|
+
`BLUME_AUDIT_REDIRECT_NOT_SERVED` · error · needs `--url`
|
|
366
|
+
|
|
367
|
+
Fix: Deploy the redirect file your host reads (see Redirects in the deployment docs), or name the host in `deployment`.
|
|
368
|
+
|
|
369
|
+
A warning instead when the old URL answers 200 (the meta-refresh page) or redirects somewhere other than the configured destination.
|
|
370
|
+
|
|
354
371
|
### Social cards
|
|
355
372
|
|
|
356
373
|
#### Open Graph tags missing or incomplete [#og-incomplete]
|
|
@@ -445,6 +462,24 @@ Fix: Point the hreflang alternate at a page that exists and is canonical.
|
|
|
445
462
|
|
|
446
463
|
Fix: Each language in an hreflang group must name exactly one page.
|
|
447
464
|
|
|
465
|
+
### Accessibility
|
|
466
|
+
|
|
467
|
+
These run on your theme config, not on each page: a theme color is one choice for the whole site. The check resolves colors the way the build does (a preset's shade for each mode, and white or dark labels on fills) and measures every text color the theme draws against the WCAG AA ratio for body text, 4.5:1, in light and dark mode.
|
|
468
|
+
|
|
469
|
+
#### Theme colors miss WCAG AA contrast [#theme-contrast-low]
|
|
470
|
+
|
|
471
|
+
`BLUME_AUDIT_THEME_CONTRAST_LOW` · warning · from the theme config
|
|
472
|
+
|
|
473
|
+
Fix: Pick a darker shade for light mode or a lighter one for dark mode, per mode with `theme.accent: { light, dark }`.
|
|
474
|
+
|
|
475
|
+
It checks accent text on the page, labels on accent and `action` fills, and body and secondary text on a custom `background`. Each finding names the pair, the mode, and its ratio.
|
|
476
|
+
|
|
477
|
+
#### Theme color can't be checked for contrast [#theme-color-unchecked]
|
|
478
|
+
|
|
479
|
+
`BLUME_AUDIT_THEME_COLOR_UNCHECKED` · info · from the theme config
|
|
480
|
+
|
|
481
|
+
Fix: Write the color as hex, `rgb()`, `hsl()`, `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()`, or a named color so its contrast can be checked.
|
|
482
|
+
|
|
448
483
|
### Assets
|
|
449
484
|
|
|
450
485
|
#### Missing alt text [#image-alt-missing]
|
|
@@ -489,7 +524,7 @@ Fix: Load the subresource over HTTPS — browsers block mixed content.
|
|
|
489
524
|
|
|
490
525
|
`BLUME_AUDIT_INDEXABLE_PAGE_NOT_IN_SITEMAP` · warning · from the built HTML
|
|
491
526
|
|
|
492
|
-
Fix: Remove `draft`/`hidden`/`noindex` from the page's frontmatter if it should be indexed.
|
|
527
|
+
Fix: Remove `draft`/`hidden`/`noindex` from the page's frontmatter if it should be indexed. A `public/sitemap.xml` replaces the generated sitemap, so add the page there or delete that file.
|
|
493
528
|
|
|
494
529
|
#### Noindex page in sitemap [#noindex-in-sitemap]
|
|
495
530
|
|
|
@@ -559,6 +594,14 @@ Fix: Every robots.txt line must be a `Field: value` directive or a comment.
|
|
|
559
594
|
|
|
560
595
|
Fix: A page can't be both disallowed in robots.txt and advertised in the sitemap.
|
|
561
596
|
|
|
597
|
+
#### robots.txt blocks one crawler from pages in the sitemap [#robots-blocks-crawler]
|
|
598
|
+
|
|
599
|
+
`BLUME_AUDIT_ROBOTS_BLOCKS_CRAWLER` · warning · from the built HTML
|
|
600
|
+
|
|
601
|
+
Fix: Narrow or remove the rule in that crawler's `User-agent` group if it should read these pages. Blocking an AI crawler on purpose is fine; skip this check.
|
|
602
|
+
|
|
603
|
+
A crawler named in its own `User-agent` group follows only that group, so a rule there (`User-agent: GPTBot` then `Disallow: /`) shuts it out while every other crawler reads the page. The audit reports each crawler once, at the rule that blocks its first page.
|
|
604
|
+
|
|
562
605
|
#### robots.txt does not reference the sitemap [#robots-sitemap-missing]
|
|
563
606
|
|
|
564
607
|
`BLUME_AUDIT_ROBOTS_SITEMAP_MISSING` · info · from the built HTML
|
package/docs/cli/doctor.mdx
CHANGED
|
@@ -9,16 +9,20 @@ description: blume doctor diagnoses configuration and content problems before yo
|
|
|
9
9
|
blume doctor
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
+
`blume init` also adds it to `package.json` as a `doctor` script. With pnpm, run that as `pnpm run doctor` (`pnpm --filter <workspace> run doctor` from a monorepo root): a bare `pnpm doctor` runs pnpm's own built-in `doctor` command instead of the script.
|
|
13
|
+
|
|
12
14
|
## What it checks
|
|
13
15
|
|
|
14
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.
|
|
15
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".
|
|
16
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 reference: a warning (`BLUME_NAV_MISSING_PAGE`), the same one `blume dev` and `blume build` print.
|
|
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.
|
|
17
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).
|
|
18
22
|
- **Packages your config needs** that aren't installed — the SDK a search, content source, or assistant adapter imports, a deployment adapter's `@astrojs/*` package, or the renderer for Vue or Svelte islands: an error naming each package, with the install command for your package manager. `blume build` stops on the same check.
|
|
19
23
|
- **`components.ts` overrides** Blume can't plan — an inline or computed entry, or an import whose file doesn't exist: an error for each, at its line.
|
|
20
24
|
- **A version-shaped folder** (`v1.0/`) on a site with no `versions` configured, which would otherwise build as ordinary content: a warning pointing at [`blume version`](/docs/cli/version).
|
|
21
|
-
- **Secrets an enabled feature reads** that aren't set, such as `MIXEDBREAD_API_KEY` or `OPENROUTER_API_KEY`: a warning naming the variable. Doctor loads `.env` and `.env.local` first, like `blume dev` and `blume build
|
|
25
|
+
- **Secrets an enabled feature reads** that aren't set, such as `MIXEDBREAD_API_KEY` or `OPENROUTER_API_KEY`: a warning naming the variable. Doctor loads `.env` and `.env.local` first, like `blume dev` and `blume build`, and checks before any remote content source fetches, so the warning still prints when a source then fails without its token.
|
|
22
26
|
|
|
23
27
|
## The summary
|
|
24
28
|
|
package/docs/cli/evals.mdx
CHANGED
|
@@ -25,7 +25,7 @@ blume eval 4 question(s) · Codex
|
|
|
25
25
|
|
|
26
26
|
## How it works
|
|
27
27
|
|
|
28
|
-
Each question runs through two agent sessions, using an agent CLI you already have installed — [Codex](https://developers.openai.com/codex/cli) by default, or [Claude Code](https://claude.com/claude-code) with `--agent claude`. Blume holds no API keys and calls no model itself. With Codex, both sessions also run without Codex's shell, command, and image tools, and inherit none of your environment variables.
|
|
28
|
+
Each question runs through two agent sessions, using an agent CLI you already have installed — [Codex](https://developers.openai.com/codex/cli) by default, or [Claude Code](https://claude.com/claude-code) with `--agent claude`. Blume holds no API keys and calls no model itself. With Codex, both sessions also run without Codex's shell, command, and image tools, and inherit none of your environment variables. With Claude Code, both sessions run with every built-in tool turned off and skip your Claude Code settings files and `CLAUDE.md`, so your hooks, plugins, and memory can't tell the reader what the docs don't. Your Claude Code login still works; set anything else it needs, such as `ANTHROPIC_API_KEY`, in your shell rather than in `settings.json`.
|
|
29
29
|
|
|
30
30
|
1. **The reader** answers the question using _only_ your documentation. It runs in an empty directory with its file, shell, and web tools disabled, connected to a private [MCP server](/docs/discoverability/mcp) that serves your docs — the same `search_docs`/`get_page` tools a real agent uses against your deployed site. It cannot read your repo, so it experiences the docs exactly like a fresh user: what isn't written doesn't exist.
|
|
31
31
|
2. **The judge** grades the answer against the facts you listed, with no tools at all. Paraphrase passes; a missing or contradicted fact fails — and so does "the documentation doesn't say."
|
|
@@ -82,9 +82,9 @@ blume eval --threshold 0.8 # at least 80% must pass
|
|
|
82
82
|
blume eval --json # machine-readable report on stdout
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
The JSON report carries the same `diagnostics` + `summary` shape as `blume validate --json` and `blume audit --json`, with the per-question results (answer, score, missing facts, cost) alongside.
|
|
85
|
+
The JSON report carries the same `diagnostics` + `summary` shape as `blume validate --json` and `blume audit --json`, with the per-question results (answer, score, missing facts, and with Claude Code, cost) alongside.
|
|
86
86
|
|
|
87
|
-
Because each question is two model sessions, an eval run costs real money and minutes
|
|
87
|
+
Because each question is two model sessions, an eval run costs real money and minutes. With Claude Code, the per-question spend is printed as it runs and totaled in the summary; Codex doesn't report its spend, so a Codex run shows none. A sensible CI setup runs `blume eval` on docs changes rather than every push.
|
|
88
88
|
|
|
89
89
|
## Fixing the findings
|
|
90
90
|
|
|
@@ -94,7 +94,7 @@ Each failure names the missing facts and the page that should state them. To han
|
|
|
94
94
|
blume eval --fix
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
This writes the full JSON report to a file and opens the agent interactively with a prompt that walks it through each failed question: read the named page, add the missing facts in the page's voice, and rerun `blume eval` until everything passes. The session is interactive by design — you review the edits through the agent's own permission flow — and the agent is told never to delete questions or weaken expected facts to get to green.
|
|
97
|
+
This writes the full JSON report to a file and opens the agent interactively with a prompt that walks it through each failed question: read the named page, add the missing facts in the page's voice, and rerun `blume eval` with the run's own `--agent`, `--file`, `--threshold`, and `--timeout` until everything passes. The session is interactive by design — you review the edits through the agent's own permission flow — and the agent is told never to delete questions or weaken expected facts to get to green.
|
|
98
98
|
|
|
99
99
|
## Flags
|
|
100
100
|
|
package/docs/cli/index.mdx
CHANGED
|
@@ -25,6 +25,7 @@ blume <command> [options]
|
|
|
25
25
|
| [`blume eval`](/docs/cli/evals) | Test the docs: an agent answers your questions using only the documentation. |
|
|
26
26
|
| [`blume translate`](/docs/cli/translate) | Translate docs into the configured locales with a local agent CLI. |
|
|
27
27
|
| [`blume version [id]`](/docs/cli/version) | Freeze the current docs as an archived version (no id lists configured versions). |
|
|
28
|
+
| [`blume skill`](/docs/discoverability/agent-discovery#your-sites-skill) | Write your docs' agent skill with Codex or Claude Code, in place of the generated one. |
|
|
28
29
|
| [`blume migrate [source]`](/docs/migrating) | Move a Mintlify, Fumadocs, Docusaurus, Starlight, or Nextra site to Blume with Codex or Claude Code. |
|
|
29
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. |
|
|
30
31
|
|
package/docs/cli/translate.mdx
CHANGED
|
@@ -43,6 +43,7 @@ Translations you wrote by hand are **adopted, never overwritten**: a translation
|
|
|
43
43
|
The agent is never trusted with structure. Before writing, Blume checks each reply and rebuilds the file from the source:
|
|
44
44
|
|
|
45
45
|
- The frontmatter is reconstructed from the source file's data, with only the six translatable values overlaid — keys the agent invented are dropped, keys it deleted are restored, and `slug`, `icon`, `order`, and dates are source-verbatim by construction.
|
|
46
|
+
- `seo.canonical` is the one source key left out. It names a page in the source language, and a translation that canonicalizes to another language drops out of search in its own, so the translation gets the default canonical, its own URL.
|
|
46
47
|
- The number of code fences must match the source, the body must be non-empty, and the frontmatter must parse.
|
|
47
48
|
- Every heading is pinned to its source heading's anchor id with a trailing [`[#id]` marker](/docs/content/syntax#custom-anchors), unless the translation already pins one, so `#fragment` links resolve identically in every language. Headings pair up positionally, so a translation whose heading structure doesn't match the source gets no pins.
|
|
48
49
|
|
package/docs/cli/validate.mdx
CHANGED
|
@@ -9,10 +9,10 @@ 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.
|
|
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 exactly 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. An `href={…}` expression isn't checked.
|
|
13
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)) or a raw HTML element's `id` attribute — with misses reported as warnings. Ids inside code blocks, inline code, HTML comments, and `<Prompt>` blocks don't count.
|
|
14
14
|
- **Asset links** are checked where the file lives: an absolute path (`/logo.png`) against the `public/` directory, a relative image embed (``) against the page's own folder. A plain link to a relative path still resolves as a site route — only image embeds go through the image pipeline.
|
|
15
|
-
- **External links** are only checked with [`--external`](#flags) (off by default since it requires the network)
|
|
15
|
+
- **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
16
|
|
|
17
17
|
## What counts as a page
|
|
18
18
|
|
|
@@ -21,6 +21,7 @@ Links resolve against everything the built site serves, not just Markdown pages:
|
|
|
21
21
|
## Flags
|
|
22
22
|
|
|
23
23
|
- `--external` — also check external `http(s)` links over the network.
|
|
24
|
+
- `--ignore <glob>` — with `--external`, don't request an external link whose URL matches the glob, and report nothing for it. The glob is matched against the link's full URL, scheme included: `*` matches within one path segment and `**` across segments, so `--ignore "https://api.acme.example/**"` skips every link to that host and `--ignore "http://localhost:*/**"` every local server. Repeat the flag for more patterns, and quote each one so your shell doesn't expand it. Internal links are always checked: they resolve against your own pages, so fix a broken one or add a [redirect](/docs/deployment#redirects).
|
|
24
25
|
- `--strict` — exit non-zero on warnings too. Info-level notes stay advisory.
|
|
25
26
|
- `--json` — emit the diagnostics as JSON on stdout instead of the terminal report.
|
|
26
27
|
|
|
@@ -32,7 +33,7 @@ Links resolve against everything the built site serves, not just Markdown pages:
|
|
|
32
33
|
| `BLUME_BROKEN_ANCHOR` | warning | The page exists but has no anchor matching the fragment. |
|
|
33
34
|
| `BLUME_BROKEN_ASSET` | warning | An absolute path isn't in `public/`, or a relative image embed isn't beside the page. |
|
|
34
35
|
| `BLUME_ASSETS_UNCHECKED` | info | There is no `public/` directory, so absolute asset paths weren't checked. |
|
|
35
|
-
| `BLUME_DEAD_LINK` | error or warning | An external link (with `--external`) returned 404/410 or
|
|
36
|
+
| `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). |
|
|
36
37
|
|
|
37
38
|
The exit code is the contract: errors exit non-zero, and `--strict` makes warnings do the same.
|
|
38
39
|
|
|
@@ -27,6 +27,8 @@ Analytics loads in **production builds only**. The scripts are emitted by `blume
|
|
|
27
27
|
Analytics is opt-in. With no `analytics` list (or an empty one), Blume injects nothing.
|
|
28
28
|
:::
|
|
29
29
|
|
|
30
|
+
To ask readers first, set [`consent`](/docs/configuration/consent): every adapter here then waits until the reader allows analytics.
|
|
31
|
+
|
|
30
32
|
Every identifier below — a project key, a measurement ID, a site token — is the public, browser-side one from the provider's own install snippet. Each adapter renders that snippet, so it's safe to commit to your docs repository; Blume never asks for a secret.
|
|
31
33
|
|
|
32
34
|
## Adapters
|
|
@@ -429,4 +431,4 @@ analytics: [
|
|
|
429
431
|
|
|
430
432
|
## Custom events
|
|
431
433
|
|
|
432
|
-
Blume's page feedback
|
|
434
|
+
Blume's page feedback (`feedback`, and `feedback_comment` when [written feedback](/docs/configuration#written-feedback) is on), [search](/docs/configuration/search#search-analytics) (`search`, `search_select`), [assistant](/docs/configuration/assistant#analytics) (`ask`, `ask_answer`, `ask_error`), and [narration](/docs/configuration/narration#analytics) player (`narration_play`, `narration_complete`) send custom events through every configured adapter that has a client API — PostHog, Mixpanel, Heap, Segment, Hightouch, Amplitude, LogRocket, Adobe, Google Analytics, Google Tag Manager (as a `{ event }` push on `window.dataLayer`), Plausible, Databuddy, Fathom, OneDollarStats (with each property value as a string), Pirsch, Clarity, Hotjar, and Vercel. Fathom, Clarity, and Hotjar take an event's name alone, so they count each event without its properties. Cloudflare and Clearbit have no event API. Every event also fires as a `blume:track` CustomEvent on `window` with `{ event, props }` in `detail`, so a `script()` adapter can forward it anywhere else. The assistant never sends a question's text to a provider, and search sends its queries as typed unless you set [`search.analytics.queries`](/docs/configuration/search#search-analytics) to `false`, which sends each query's length instead; either way the text still reaches the `blume:track` event, for a listener you write to forward. For deploying your built site, see [Deployment](/docs/deployment).
|