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.
Files changed (607) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +142 -0
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
  5. package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
  6. package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
  7. package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
  8. package/dist/cli/chunk-150jk7km.js +52 -0
  9. package/dist/cli/chunk-150jk7km.js.map +10 -0
  10. package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
  11. package/dist/cli/chunk-313vnn40.js.map +10 -0
  12. package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
  13. package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
  14. package/dist/cli/chunk-3x6x3pph.js.map +10 -0
  15. package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
  16. package/dist/cli/chunk-42t4jxdx.js.map +12 -0
  17. package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
  18. package/dist/cli/chunk-54ztw1nj.js.map +10 -0
  19. package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
  20. package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
  21. package/dist/cli/chunk-66w9j7p6.js +322 -0
  22. package/dist/cli/chunk-66w9j7p6.js.map +14 -0
  23. package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
  24. package/dist/cli/chunk-7ppf1rva.js.map +10 -0
  25. package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
  26. package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
  27. package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
  28. package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
  29. package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
  30. package/dist/cli/chunk-cfyg47zg.js.map +10 -0
  31. package/dist/cli/chunk-cm89scdv.js +443 -0
  32. package/dist/cli/chunk-cm89scdv.js.map +11 -0
  33. package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
  34. package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
  35. package/dist/cli/chunk-e6atmn4h.js.map +36 -0
  36. package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
  37. package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
  38. package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
  39. package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
  40. package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
  41. package/dist/cli/chunk-ehweg4fr.js.map +218 -0
  42. package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
  43. package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
  44. package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
  45. package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
  46. package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
  47. package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
  48. package/dist/cli/chunk-gb420vvz.js.map +17 -0
  49. package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
  50. package/dist/cli/chunk-hebn0tpx.js.map +14 -0
  51. package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
  52. package/dist/cli/chunk-htrwgabr.js.map +15 -0
  53. package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
  54. package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
  55. package/dist/cli/chunk-j134vrp2.js +65 -0
  56. package/dist/cli/chunk-j134vrp2.js.map +10 -0
  57. package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
  58. package/dist/cli/chunk-kwrg63tm.js +31 -0
  59. package/dist/cli/chunk-kwrg63tm.js.map +10 -0
  60. package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
  61. package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
  62. package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
  63. package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
  64. package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
  65. package/dist/cli/chunk-ncj7w596.js.map +35 -0
  66. package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
  67. package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
  68. package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
  69. package/dist/cli/chunk-nrns10mj.js.map +10 -0
  70. package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
  71. package/dist/cli/chunk-t2m5j4pr.js +104 -0
  72. package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
  73. package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
  74. package/dist/cli/chunk-tphac74f.js +126 -0
  75. package/dist/cli/chunk-tphac74f.js.map +11 -0
  76. package/dist/cli/chunk-w1r4vase.js +18 -0
  77. package/dist/cli/chunk-w1r4vase.js.map +10 -0
  78. package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
  79. package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
  80. package/dist/cli/index.js +31 -20
  81. package/dist/cli/index.js.map +5 -5
  82. package/dist/types/ai/agent-surface.d.ts +8 -7
  83. package/dist/types/ai/ai-catalog.d.ts +7 -0
  84. package/dist/types/ai/ask-context.d.ts +26 -0
  85. package/dist/types/ai/ask.d.ts +271 -58
  86. package/dist/types/ai/component-markdown.d.ts +2 -0
  87. package/dist/types/ai/index.d.ts +2 -2
  88. package/dist/types/ai/openapi-components.d.ts +4 -1
  89. package/dist/types/ai/site-skill.d.ts +26 -0
  90. package/dist/types/ai/skills.d.ts +16 -0
  91. package/dist/types/astro/integration.d.ts +9 -0
  92. package/dist/types/astro/markdown-negotiation.d.ts +3 -0
  93. package/dist/types/astro/pages.d.ts +10 -0
  94. package/dist/types/captcha/hcaptcha.d.ts +27 -0
  95. package/dist/types/captcha/index.d.ts +28 -0
  96. package/dist/types/captcha/schema.d.ts +29 -0
  97. package/dist/types/captcha/turnstile.d.ts +28 -0
  98. package/dist/types/cli/init/scaffold.d.ts +1 -1
  99. package/dist/types/components/content/api-field.d.ts +62 -0
  100. package/dist/types/components/content/api-page.d.ts +100 -0
  101. package/dist/types/components/layout/nav-utils.d.ts +26 -0
  102. package/dist/types/components/openapi/code-samples.d.ts +29 -0
  103. package/dist/types/components/openapi/helpers.d.ts +158 -0
  104. package/dist/types/components/openapi/security.d.ts +95 -0
  105. package/dist/types/components/openapi/snippets.d.ts +60 -0
  106. package/dist/types/consent/ethyca.d.ts +48 -0
  107. package/dist/types/consent/index.d.ts +37 -0
  108. package/dist/types/consent/native.d.ts +28 -0
  109. package/dist/types/consent/osano.d.ts +42 -0
  110. package/dist/types/consent/schema.d.ts +110 -0
  111. package/dist/types/core/changelog-index.d.ts +8 -0
  112. package/dist/types/core/config-input.d.ts +217 -23
  113. package/dist/types/core/data.d.ts +53 -4
  114. package/dist/types/core/footer.d.ts +8 -0
  115. package/dist/types/core/i18n-ui.d.ts +88 -0
  116. package/dist/types/core/includes.d.ts +8 -2
  117. package/dist/types/core/links.d.ts +8 -0
  118. package/dist/types/core/localizable.d.ts +7 -0
  119. package/dist/types/core/page-modes.d.ts +29 -0
  120. package/dist/types/core/probe.d.ts +2 -0
  121. package/dist/types/core/project-graph.d.ts +6 -0
  122. package/dist/types/core/redirect-patterns.d.ts +152 -0
  123. package/dist/types/core/related.d.ts +40 -0
  124. package/dist/types/core/schema.d.ts +670 -56
  125. package/dist/types/core/sources/cache.d.ts +3 -0
  126. package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
  127. package/dist/types/core/sources/contentful.d.ts +17 -1
  128. package/dist/types/core/sources/lexical.d.ts +5 -0
  129. package/dist/types/core/sources/normalize.d.ts +20 -1
  130. package/dist/types/core/sources/read.d.ts +5 -0
  131. package/dist/types/core/sources/remote.d.ts +37 -10
  132. package/dist/types/core/sources/sanity.d.ts +1 -1
  133. package/dist/types/core/types.d.ts +18 -1
  134. package/dist/types/core/variables.d.ts +42 -0
  135. package/dist/types/deploy/adapter-output.d.ts +2 -1
  136. package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
  137. package/dist/types/deploy/adapters/node.d.ts +58 -23
  138. package/dist/types/deploy/adapters/registry.d.ts +10 -0
  139. package/dist/types/deploy/adapters/types.d.ts +3 -2
  140. package/dist/types/deploy/node-headers.d.ts +13 -2
  141. package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
  142. package/dist/types/deploy/platforms/netlify.d.ts +7 -0
  143. package/dist/types/deploy/platforms/node.d.ts +3 -1
  144. package/dist/types/deploy/platforms/types.d.ts +18 -7
  145. package/dist/types/deploy/platforms/vercel.d.ts +26 -1
  146. package/dist/types/deploy/redirects.d.ts +55 -11
  147. package/dist/types/deploy/sitemap.d.ts +2 -1
  148. package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
  149. package/dist/types/markdown/code-title.d.ts +17 -0
  150. package/dist/types/markdown/features.d.ts +3 -2
  151. package/dist/types/narration/build.d.ts +70 -0
  152. package/dist/types/narration/provider.d.ts +26 -0
  153. package/dist/types/narration/script.d.ts +154 -0
  154. package/dist/types/openapi/checks.d.ts +27 -0
  155. package/dist/types/openapi/graphql.d.ts +6 -0
  156. package/dist/types/openapi/model.d.ts +27 -10
  157. package/dist/types/openapi/overlay.d.ts +54 -0
  158. package/dist/types/openapi/parse.d.ts +16 -0
  159. package/dist/types/openapi/references.d.ts +30 -4
  160. package/dist/types/ratelimit/cloudflare.d.ts +39 -0
  161. package/dist/types/ratelimit/index.d.ts +27 -0
  162. package/dist/types/ratelimit/memory.d.ts +36 -0
  163. package/dist/types/ratelimit/schema.d.ts +119 -0
  164. package/dist/types/ratelimit/upstash.d.ts +46 -0
  165. package/dist/types/ratelimit/wrangler.d.ts +23 -0
  166. package/dist/types/reference/asyncapi.d.ts +10 -10
  167. package/dist/types/reference/graphql.d.ts +89 -11
  168. package/dist/types/reference/index.d.ts +1 -1
  169. package/dist/types/reference/openapi.d.ts +33 -12
  170. package/dist/types/reference/options.d.ts +82 -6
  171. package/dist/types/reference/scalar.d.ts +13 -0
  172. package/dist/types/reference/schema.d.ts +144 -36
  173. package/dist/types/search/adapters/registry.d.ts +3 -0
  174. package/dist/types/search/adapters/typesense.d.ts +14 -4
  175. package/dist/types/search/build.d.ts +3 -1
  176. package/dist/types/search/documents.d.ts +12 -1
  177. package/dist/types/search/orama-index.d.ts +13 -9
  178. package/dist/types/search/sync/algolia.d.ts +5 -2
  179. package/dist/types/search/sync/index.d.ts +3 -1
  180. package/dist/types/search/sync/typesense.d.ts +11 -7
  181. package/dist/types/seo/metatags.d.ts +20 -0
  182. package/dist/types/sources/contentful.d.ts +16 -0
  183. package/dist/types/sources/github-releases.d.ts +8 -1
  184. package/dist/types/sources/payload.d.ts +2 -0
  185. package/dist/types/sources/registry.d.ts +54 -0
  186. package/dist/types/sources/shared.d.ts +3 -0
  187. package/dist/types/sources/strapi.d.ts +2 -0
  188. package/docs/01-quickstart.mdx +4 -2
  189. package/docs/02-deployment.mdx +71 -17
  190. package/docs/03-upgrading.mdx +4 -4
  191. package/docs/04-migrating.mdx +1 -1
  192. package/docs/advanced/changelog.mdx +13 -2
  193. package/docs/advanced/skills.mdx +15 -1
  194. package/docs/cli/audit.mdx +51 -8
  195. package/docs/cli/doctor.mdx +5 -1
  196. package/docs/cli/evals.mdx +4 -4
  197. package/docs/cli/index.mdx +1 -0
  198. package/docs/cli/translate.mdx +1 -0
  199. package/docs/cli/validate.mdx +4 -3
  200. package/docs/configuration/analytics.mdx +3 -1
  201. package/docs/configuration/assistant.mdx +194 -38
  202. package/docs/configuration/consent.mdx +100 -0
  203. package/docs/configuration/customization.mdx +8 -6
  204. package/docs/configuration/export.mdx +5 -3
  205. package/docs/configuration/index.mdx +64 -5
  206. package/docs/configuration/meta.ts +3 -0
  207. package/docs/configuration/narration.mdx +119 -0
  208. package/docs/configuration/rate-limiting.mdx +90 -0
  209. package/docs/configuration/search.mdx +63 -12
  210. package/docs/configuration/theming.mdx +3 -1
  211. package/docs/content/components.mdx +108 -2
  212. package/docs/content/frontmatter.mdx +80 -2
  213. package/docs/content/i18n.mdx +39 -4
  214. package/docs/content/includes.mdx +16 -0
  215. package/docs/content/meta.mdx +1 -0
  216. package/docs/content/meta.ts +1 -0
  217. package/docs/content/navigation.mdx +32 -10
  218. package/docs/content/sources/contentful.mdx +35 -0
  219. package/docs/content/sources/custom.mdx +43 -0
  220. package/docs/content/sources/github-releases.mdx +39 -0
  221. package/docs/content/sources/index.mdx +91 -0
  222. package/docs/content/sources/meta.ts +16 -0
  223. package/docs/content/sources/notion.mdx +32 -0
  224. package/docs/content/sources/obsidian.mdx +37 -0
  225. package/docs/content/sources/payload.mdx +31 -0
  226. package/docs/content/sources/remote-mdx.mdx +44 -0
  227. package/docs/content/sources/sanity.mdx +29 -0
  228. package/docs/content/sources/strapi.mdx +32 -0
  229. package/docs/content/syntax.mdx +69 -4
  230. package/docs/content/variables.mdx +41 -0
  231. package/docs/discoverability/agent-discovery.mdx +29 -2
  232. package/docs/discoverability/index.mdx +2 -2
  233. package/docs/discoverability/json-api.mdx +2 -0
  234. package/docs/discoverability/llms-txt.mdx +2 -2
  235. package/docs/discoverability/markdown.mdx +3 -1
  236. package/docs/discoverability/mcp.mdx +4 -0
  237. package/docs/discoverability/metadata.mdx +17 -0
  238. package/docs/discoverability/sitemap-and-robots.mdx +1 -1
  239. package/docs/references/api-pages.mdx +74 -0
  240. package/docs/references/asyncapi.mdx +4 -2
  241. package/docs/references/graphql.mdx +14 -2
  242. package/docs/references/meta.ts +1 -1
  243. package/docs/references/openapi.mdx +148 -7
  244. package/docs/references/scalar.mdx +3 -1
  245. package/package.json +43 -8
  246. package/skills/blume/SKILL.md +3 -0
  247. package/skills/blume-migrate/SKILL.md +6 -6
  248. package/skills/blume-migrate/references/docusaurus.md +7 -7
  249. package/skills/blume-migrate/references/fumadocs.md +17 -13
  250. package/skills/blume-migrate/references/mintlify.md +37 -19
  251. package/skills/blume-migrate/references/nextra.md +10 -7
  252. package/skills/blume-migrate/references/starlight.md +11 -8
  253. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
  254. package/skills/blume-write-skill/SKILL.md +82 -0
  255. package/src/ai/agent-readability.ts +2 -1
  256. package/src/ai/agent-surface.ts +9 -7
  257. package/src/ai/ai-catalog.ts +6 -3
  258. package/src/ai/ask-context.ts +103 -20
  259. package/src/ai/ask-data.ts +6 -0
  260. package/src/ai/ask-limits.ts +13 -0
  261. package/src/ai/ask-tools.ts +142 -0
  262. package/src/ai/ask.ts +354 -76
  263. package/src/ai/changelog-markdown.ts +11 -6
  264. package/src/ai/component-markdown.ts +76 -1
  265. package/src/ai/cors.ts +14 -3
  266. package/src/ai/index.ts +12 -0
  267. package/src/ai/llms.ts +6 -2
  268. package/src/ai/markdown.ts +2 -1
  269. package/src/ai/mcp/data.ts +6 -0
  270. package/src/ai/mcp/query.ts +14 -6
  271. package/src/ai/openapi-components.ts +36 -6
  272. package/src/ai/relative-links.ts +4 -38
  273. package/src/ai/site-skill.ts +274 -0
  274. package/src/ai/skills.ts +35 -2
  275. package/src/ai/write-skill.ts +97 -0
  276. package/src/astro/generate.ts +210 -66
  277. package/src/astro/index.ts +1 -0
  278. package/src/astro/integration.ts +42 -4
  279. package/src/astro/markdown-negotiation.ts +3 -0
  280. package/src/astro/module-types.ts +9 -1
  281. package/src/astro/pages.ts +23 -0
  282. package/src/astro/templates.ts +406 -108
  283. package/src/astro/variables.ts +31 -0
  284. package/src/audit/catalog.ts +38 -3
  285. package/src/audit/checks/contrast.ts +183 -0
  286. package/src/audit/checks/i18n.ts +2 -3
  287. package/src/audit/checks/indexability.ts +2 -3
  288. package/src/audit/checks/links.ts +19 -13
  289. package/src/audit/checks/network.ts +110 -6
  290. package/src/audit/checks/redirects.ts +6 -4
  291. package/src/audit/checks/robots.ts +58 -2
  292. package/src/audit/checks/sitemap.ts +2 -3
  293. package/src/audit/redirects.ts +46 -15
  294. package/src/audit/run.ts +5 -0
  295. package/src/audit/types.ts +4 -1
  296. package/src/audit/url.ts +14 -5
  297. package/src/blume-modules.d.ts +12 -1
  298. package/src/captcha/client.ts +152 -0
  299. package/src/captcha/hcaptcha.ts +36 -0
  300. package/src/captcha/index.ts +28 -0
  301. package/src/captcha/schema.ts +32 -0
  302. package/src/captcha/turnstile.ts +38 -0
  303. package/src/captcha/verify.ts +71 -0
  304. package/src/cli/args.ts +51 -0
  305. package/src/cli/build-failure.ts +23 -0
  306. package/src/cli/command-meta.ts +5 -0
  307. package/src/cli/commands/audit.ts +10 -1
  308. package/src/cli/commands/dev.ts +18 -2
  309. package/src/cli/commands/doctor.ts +67 -28
  310. package/src/cli/commands/eval.ts +36 -4
  311. package/src/cli/commands/init.ts +6 -4
  312. package/src/cli/commands/skill.ts +96 -0
  313. package/src/cli/commands/validate.ts +10 -1
  314. package/src/cli/index.ts +5 -0
  315. package/src/cli/init/scaffold.ts +3 -3
  316. package/src/cli/prepare.ts +6 -3
  317. package/src/cli/required-secrets.ts +72 -30
  318. package/src/components/BlumePage.astro +2 -0
  319. package/src/components/content/ApiEndpoint.astro +18 -0
  320. package/src/components/content/ApiField.astro +79 -0
  321. package/src/components/content/ApiPlayground.astro +66 -0
  322. package/src/components/content/ApiRail.astro +19 -0
  323. package/src/components/content/Color.astro +1 -0
  324. package/src/components/content/FileTree.astro +1 -0
  325. package/src/components/content/GithubInfo.astro +1 -0
  326. package/src/components/content/Panel.astro +1 -0
  327. package/src/components/content/ParamField.astro +25 -0
  328. package/src/components/content/RequestExample.astro +17 -0
  329. package/src/components/content/ResponseExample.astro +17 -0
  330. package/src/components/content/ResponseField.astro +32 -0
  331. package/src/components/content/Step.astro +1 -0
  332. package/src/components/content/Tile.astro +1 -0
  333. package/src/components/content/Tooltip.astro +1 -0
  334. package/src/components/content/Tree.astro +1 -0
  335. package/src/components/content/TypeTable.astro +4 -1
  336. package/src/components/content/View.astro +21 -0
  337. package/src/components/content/ViewSwitcher.astro +168 -0
  338. package/src/components/content/api-field.ts +103 -0
  339. package/src/components/content/api-page.ts +248 -0
  340. package/src/components/content/mermaid-element.ts +15 -1
  341. package/src/components/content/view-switcher.ts +71 -0
  342. package/src/components/index.ts +2 -0
  343. package/src/components/islands/Assistant.astro +10 -1
  344. package/src/components/islands/assistant.tsx +104 -14
  345. package/src/components/islands/code-question.ts +62 -0
  346. package/src/components/islands/hooks.ts +136 -21
  347. package/src/components/islands/support-link.ts +68 -0
  348. package/src/components/layout/Analytics.astro +11 -2
  349. package/src/components/layout/Banner.astro +14 -10
  350. package/src/components/layout/Breadcrumbs.astro +6 -2
  351. package/src/components/layout/ConsentBanner.astro +62 -0
  352. package/src/components/layout/ConsentHead.astro +38 -0
  353. package/src/components/layout/Directory.astro +94 -0
  354. package/src/components/layout/DrawerSwitchers.astro +51 -0
  355. package/src/components/layout/Empty.astro +2 -2
  356. package/src/components/layout/Header.astro +122 -80
  357. package/src/components/layout/LanguageSwitcher.astro +48 -15
  358. package/src/components/layout/NarrationPlayer.astro +1085 -0
  359. package/src/components/layout/NavSelector.astro +33 -7
  360. package/src/components/layout/PageActions.astro +139 -24
  361. package/src/components/layout/PageFeedback.astro +54 -49
  362. package/src/components/layout/PageLayout.astro +71 -3
  363. package/src/components/layout/ReferenceLayout.astro +17 -6
  364. package/src/components/layout/RelatedPages.astro +42 -0
  365. package/src/components/layout/RootLayout.astro +318 -47
  366. package/src/components/layout/Search.astro +47 -19
  367. package/src/components/layout/SiteFooter.astro +124 -0
  368. package/src/components/layout/SiteMetatags.astro +16 -0
  369. package/src/components/layout/TableOfContents.astro +24 -17
  370. package/src/components/layout/consent/native.ts +79 -0
  371. package/src/components/layout/consent/types.ts +37 -0
  372. package/src/components/layout/footer-links.ts +53 -0
  373. package/src/components/layout/footer-socials.ts +87 -0
  374. package/src/components/layout/head-scripts.ts +6 -1
  375. package/src/components/layout/locale-redirect.ts +107 -0
  376. package/src/components/layout/nav-utils.ts +83 -0
  377. package/src/components/layout/page-feedback.ts +96 -0
  378. package/src/components/layout/search/algolia.ts +10 -1
  379. package/src/components/layout/search/analytics.ts +126 -0
  380. package/src/components/layout/search/endpoint.ts +48 -5
  381. package/src/components/layout/search/flexsearch.ts +17 -5
  382. package/src/components/layout/search/orama-cloud.ts +26 -14
  383. package/src/components/layout/search/pagefind.ts +114 -5
  384. package/src/components/layout/search/types.ts +32 -0
  385. package/src/components/layout/search/typesense.ts +19 -3
  386. package/src/components/openapi/AsyncApiOperation.astro +14 -7
  387. package/src/components/openapi/Authorization.astro +10 -0
  388. package/src/components/openapi/GraphqlOperation.astro +5 -0
  389. package/src/components/openapi/Operation.astro +184 -13
  390. package/src/components/openapi/ParametersTable.astro +8 -4
  391. package/src/components/openapi/Playground.astro +7 -1
  392. package/src/components/openapi/RequestBody.astro +24 -5
  393. package/src/components/openapi/RequestPanel.astro +59 -7
  394. package/src/components/openapi/Responses.astro +7 -4
  395. package/src/components/openapi/SchemaTable.astro +15 -3
  396. package/src/components/openapi/async-snippets.ts +65 -9
  397. package/src/components/openapi/async.ts +123 -29
  398. package/src/components/openapi/code-samples.ts +97 -0
  399. package/src/components/openapi/graphql-helpers.ts +35 -12
  400. package/src/components/openapi/helpers.ts +36 -2
  401. package/src/components/openapi/message-model.ts +54 -11
  402. package/src/components/openapi/message.ts +14 -4
  403. package/src/components/openapi/operation-model.ts +16 -7
  404. package/src/components/openapi/playground-client.ts +24 -5
  405. package/src/components/openapi/playground-schema.ts +1 -1
  406. package/src/components/openapi/schema-tree.ts +44 -14
  407. package/src/components/openapi/security.ts +16 -3
  408. package/src/components/openapi/snippets.ts +873 -10
  409. package/src/components/openapi/validate-json.ts +4 -3
  410. package/src/components/props.ts +6 -0
  411. package/src/consent/client.ts +95 -0
  412. package/src/consent/clients.ts +19 -0
  413. package/src/consent/ethyca.ts +71 -0
  414. package/src/consent/head.ts +24 -0
  415. package/src/consent/index.ts +37 -0
  416. package/src/consent/init.ts +29 -0
  417. package/src/consent/native.ts +36 -0
  418. package/src/consent/osano.ts +59 -0
  419. package/src/consent/schema.ts +30 -0
  420. package/src/core/builtin-tags.ts +5 -0
  421. package/src/core/changelog-index.ts +31 -1
  422. package/src/core/client-address.ts +19 -0
  423. package/src/core/component-diagnostics.ts +53 -0
  424. package/src/core/component-overrides.ts +32 -0
  425. package/src/core/config-input.ts +225 -23
  426. package/src/core/data.ts +46 -4
  427. package/src/core/diagnostics.ts +8 -2
  428. package/src/core/footer.ts +26 -0
  429. package/src/core/graph.ts +39 -36
  430. package/src/core/i18n-ui.ts +84 -2
  431. package/src/core/includes.ts +21 -4
  432. package/src/core/links.ts +63 -19
  433. package/src/core/localizable.ts +26 -0
  434. package/src/core/navigation.ts +43 -12
  435. package/src/core/page-modes.ts +56 -0
  436. package/src/core/probe.ts +26 -6
  437. package/src/core/project-graph.ts +163 -16
  438. package/src/core/redirect-patterns.ts +520 -0
  439. package/src/core/related.ts +131 -0
  440. package/src/core/schema.ts +339 -66
  441. package/src/core/sources/cache.ts +6 -0
  442. package/src/core/sources/contentful-rich-text.ts +29 -6
  443. package/src/core/sources/contentful.ts +135 -25
  444. package/src/core/sources/filesystem.ts +26 -4
  445. package/src/core/sources/github-releases.ts +12 -1
  446. package/src/core/sources/lexical.ts +15 -10
  447. package/src/core/sources/mdx-remote.ts +62 -10
  448. package/src/core/sources/normalize.ts +228 -41
  449. package/src/core/sources/notion.ts +7 -1
  450. package/src/core/sources/obsidian.ts +16 -3
  451. package/src/core/sources/payload.ts +38 -15
  452. package/src/core/sources/read.ts +8 -3
  453. package/src/core/sources/remote.ts +72 -15
  454. package/src/core/sources/resolve.ts +11 -1
  455. package/src/core/sources/sanity.ts +43 -25
  456. package/src/core/sources/strapi.ts +2 -2
  457. package/src/core/types.ts +19 -1
  458. package/src/core/ui-packs/ar.ts +44 -0
  459. package/src/core/ui-packs/bg.ts +46 -0
  460. package/src/core/ui-packs/bn.ts +44 -0
  461. package/src/core/ui-packs/ca.ts +47 -0
  462. package/src/core/ui-packs/cs.ts +45 -0
  463. package/src/core/ui-packs/da.ts +46 -0
  464. package/src/core/ui-packs/de.ts +47 -0
  465. package/src/core/ui-packs/el.ts +46 -0
  466. package/src/core/ui-packs/es.ts +47 -0
  467. package/src/core/ui-packs/fa.ts +46 -0
  468. package/src/core/ui-packs/fi.ts +46 -0
  469. package/src/core/ui-packs/fr.ts +47 -0
  470. package/src/core/ui-packs/he.ts +44 -0
  471. package/src/core/ui-packs/hi.ts +45 -0
  472. package/src/core/ui-packs/hr.ts +46 -0
  473. package/src/core/ui-packs/hu.ts +45 -0
  474. package/src/core/ui-packs/id.ts +46 -0
  475. package/src/core/ui-packs/it.ts +46 -0
  476. package/src/core/ui-packs/ja.ts +46 -0
  477. package/src/core/ui-packs/ko.ts +45 -0
  478. package/src/core/ui-packs/nl.ts +47 -0
  479. package/src/core/ui-packs/no.ts +45 -0
  480. package/src/core/ui-packs/pl.ts +46 -0
  481. package/src/core/ui-packs/pt-br.ts +47 -0
  482. package/src/core/ui-packs/pt.ts +46 -0
  483. package/src/core/ui-packs/ro.ts +46 -0
  484. package/src/core/ui-packs/ru.ts +46 -0
  485. package/src/core/ui-packs/sk.ts +45 -0
  486. package/src/core/ui-packs/sr.ts +46 -0
  487. package/src/core/ui-packs/sv.ts +45 -0
  488. package/src/core/ui-packs/th.ts +44 -0
  489. package/src/core/ui-packs/tr.ts +46 -0
  490. package/src/core/ui-packs/uk.ts +46 -0
  491. package/src/core/ui-packs/vi.ts +46 -0
  492. package/src/core/ui-packs/zh-tw.ts +44 -0
  493. package/src/core/ui-packs/zh.ts +44 -0
  494. package/src/core/variables.ts +103 -0
  495. package/src/deploy/adapter-output.ts +7 -2
  496. package/src/deploy/adapters/cloudflare.ts +7 -5
  497. package/src/deploy/adapters/node.ts +47 -9
  498. package/src/deploy/adapters/types.ts +7 -3
  499. package/src/deploy/artifacts.ts +79 -9
  500. package/src/deploy/cloudflare-negotiation.ts +35 -5
  501. package/src/deploy/headers.ts +2 -1
  502. package/src/deploy/node-headers.ts +63 -9
  503. package/src/deploy/platforms/cloudflare.ts +45 -9
  504. package/src/deploy/platforms/netlify.ts +35 -2
  505. package/src/deploy/platforms/node.ts +12 -2
  506. package/src/deploy/platforms/types.ts +21 -7
  507. package/src/deploy/platforms/vercel.ts +149 -17
  508. package/src/deploy/redirects.ts +151 -24
  509. package/src/deploy/rss.ts +3 -1
  510. package/src/deploy/sitemap.ts +39 -5
  511. package/src/deploy/vercel-negotiation.ts +326 -102
  512. package/src/eval/agents.ts +18 -1
  513. package/src/eval/prompts.ts +6 -3
  514. package/src/eval/report.ts +34 -13
  515. package/src/eval/run.ts +5 -0
  516. package/src/markdown/api-rail.ts +259 -0
  517. package/src/markdown/code-title.ts +35 -9
  518. package/src/markdown/features.ts +3 -2
  519. package/src/markdown/fence-meta.ts +2 -0
  520. package/src/markdown/include.ts +11 -1
  521. package/src/markdown/index.ts +28 -5
  522. package/src/markdown/math.ts +4 -4
  523. package/src/markdown/relative-links.ts +3 -2
  524. package/src/markdown/variables.ts +56 -0
  525. package/src/markdown/views.ts +82 -0
  526. package/src/narration/build.ts +412 -0
  527. package/src/narration/player.ts +249 -0
  528. package/src/narration/provider.ts +29 -0
  529. package/src/narration/script.ts +592 -0
  530. package/src/og/card.ts +7 -6
  531. package/src/openapi/checks.ts +273 -0
  532. package/src/openapi/graphql-build.ts +21 -0
  533. package/src/openapi/graphql.ts +11 -0
  534. package/src/openapi/model.ts +72 -27
  535. package/src/openapi/overlay.ts +256 -0
  536. package/src/openapi/parse.ts +182 -4
  537. package/src/openapi/references.ts +64 -8
  538. package/src/openapi/render-mdx.ts +5 -1
  539. package/src/openapi/scalar.ts +40 -6
  540. package/src/openapi/source.ts +40 -15
  541. package/src/ratelimit/cloudflare.ts +54 -0
  542. package/src/ratelimit/index.ts +30 -0
  543. package/src/ratelimit/memory.ts +45 -0
  544. package/src/ratelimit/runtime.ts +247 -0
  545. package/src/ratelimit/schema.ts +28 -0
  546. package/src/ratelimit/upstash.ts +60 -0
  547. package/src/ratelimit/wrangler.ts +70 -0
  548. package/src/reference/asyncapi.ts +2 -2
  549. package/src/reference/graphql.ts +20 -3
  550. package/src/reference/index.ts +1 -0
  551. package/src/reference/openapi.ts +21 -7
  552. package/src/reference/options.ts +80 -8
  553. package/src/reference/scalar.ts +33 -8
  554. package/src/registry/eject.ts +23 -5
  555. package/src/registry/registry.ts +7 -0
  556. package/src/search/adapters/locale-scope.ts +30 -0
  557. package/src/search/adapters/typesense.ts +14 -4
  558. package/src/search/build.ts +21 -3
  559. package/src/search/documents.ts +26 -2
  560. package/src/search/orama-index.ts +191 -34
  561. package/src/search/pagefind-ranking.ts +39 -0
  562. package/src/search/source-pages.ts +29 -0
  563. package/src/search/sync/algolia.ts +111 -10
  564. package/src/search/sync/index.ts +52 -13
  565. package/src/search/sync/orama-cloud.ts +3 -0
  566. package/src/search/sync/typesense.ts +76 -26
  567. package/src/seo/metatags.ts +67 -0
  568. package/src/sources/contentful.ts +12 -0
  569. package/src/sources/github-releases.ts +7 -1
  570. package/src/sources/shared.ts +3 -0
  571. package/src/theme/chrome-icons.ts +1 -0
  572. package/src/theme/color.ts +500 -0
  573. package/src/theme/entry.ts +85 -6
  574. package/src/theme/palette.ts +121 -45
  575. package/src/translate/prompts.ts +1 -0
  576. package/src/translate/validate.ts +31 -3
  577. package/src/upgrade/upgrade.ts +4 -171
  578. package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
  579. package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
  580. package/dist/cli/chunk-35d4wj9f.js.map +0 -15
  581. package/dist/cli/chunk-364znk6q.js +0 -75
  582. package/dist/cli/chunk-364znk6q.js.map +0 -11
  583. package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
  584. package/dist/cli/chunk-8ktnccpt.js.map +0 -10
  585. package/dist/cli/chunk-9t7a85s3.js.map +0 -10
  586. package/dist/cli/chunk-b07cmahc.js +0 -145
  587. package/dist/cli/chunk-b07cmahc.js.map +0 -11
  588. package/dist/cli/chunk-c8chx29p.js.map +0 -36
  589. package/dist/cli/chunk-e04dxsz1.js +0 -39
  590. package/dist/cli/chunk-e04dxsz1.js.map +0 -10
  591. package/dist/cli/chunk-j85vccga.js.map +0 -36
  592. package/dist/cli/chunk-p3v96n38.js.map +0 -10
  593. package/dist/cli/chunk-pehfxfta.js.map +0 -10
  594. package/dist/cli/chunk-pv29h0wf.js.map +0 -190
  595. package/dist/cli/chunk-q58y5e6a.js.map +0 -10
  596. package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
  597. package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
  598. package/dist/cli/chunk-yfyb25rh.js.map +0 -14
  599. package/docs/content/sources.mdx +0 -334
  600. /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
  601. /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
  602. /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
  603. /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
  604. /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
  605. /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
  606. /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
  607. /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
@@ -27,12 +27,18 @@ import type { RawMarkdownEntry } from "../ai/markdown.ts";
27
27
  import { buildMcpData } from "../ai/mcp/data.ts";
28
28
  import type { McpData } from "../ai/mcp/data.ts";
29
29
  import { buildMcpDiscovery, buildMcpServerCard } from "../ai/mcp/discovery.ts";
30
+ import { captchaSettings } from "../captcha/schema.ts";
31
+ import { parseApiEndpoint } from "../components/content/api-page.ts";
30
32
  import {
31
33
  hasDeferrableGroups,
32
34
  navVariants,
33
35
  } from "../components/layout/nav-utils.ts";
34
36
  import { normalizeBasePath, withBasePath } from "../core/base-path.ts";
35
- import { validateUsedComponents } from "../core/component-diagnostics.ts";
37
+ import { withChangelogIndexText } from "../core/changelog-index.ts";
38
+ import {
39
+ missingExampleDiagnostics,
40
+ validateUsedComponents,
41
+ } from "../core/component-diagnostics.ts";
36
42
  import {
37
43
  analyzeComponentOverrides,
38
44
  emptyComponentOverrides,
@@ -44,6 +50,7 @@ import {
44
50
  } from "../core/content-assets.ts";
45
51
  import type {
46
52
  BlumeBanner,
53
+ BlumeDataConfig,
47
54
  BlumeData,
48
55
  BlumeFavicon,
49
56
  BlumeLogo,
@@ -58,6 +65,7 @@ import {
58
65
  import { EN_UI, resolveUIStrings } from "../core/i18n-ui.ts";
59
66
  import { resolveFallbackLocale } from "../core/i18n.ts";
60
67
  import { buildIncludeGraph } from "../core/includes.ts";
68
+ import { resolveLocalizable } from "../core/localizable.ts";
61
69
  import {
62
70
  validateNavTargets,
63
71
  validateSearchPopularIcons,
@@ -85,16 +93,17 @@ import type { AsyncApiSpecValue } from "../openapi/asyncapi.ts";
85
93
  import type { ApiSpecData, HttpMethod, OpenApiData } from "../openapi/model.ts";
86
94
  import { HTTP_METHODS, withServerDefaults } from "../openapi/model.ts";
87
95
  import {
96
+ apiPagesUseBuiltinProxy,
88
97
  builtinProxyReferences,
89
98
  hasScalarReferences,
90
99
  needsPlaygroundProxy,
91
- referenceRoutes,
92
100
  } from "../openapi/references.ts";
93
101
  import { buildReferenceFiles } from "../openapi/scalar.ts";
94
102
  import { isOpenApiSource } from "../openapi/source.ts";
95
103
  import { registry } from "../registry/registry.ts";
96
104
  import { buildSearchDocuments } from "../search/documents.ts";
97
105
  import { resolveSearchPopular } from "../search/popular.ts";
106
+ import { sourcePages } from "../search/source-pages.ts";
98
107
  import {
99
108
  examplesEntryTemplate,
100
109
  tailwindEntryTemplate,
@@ -120,6 +129,7 @@ import {
120
129
  customOgRoutes,
121
130
  discoverPages,
122
131
  hasGeneratedChangelog,
132
+ navTargetRoutes,
123
133
  routeIsTaken,
124
134
  } from "./pages.ts";
125
135
  import { candidateHolding } from "./render-deps.ts";
@@ -159,6 +169,7 @@ import {
159
169
  runtimeTsconfigTemplate,
160
170
  featuresTemplate,
161
171
  navFragmentTemplate,
172
+ consentClientTemplate,
162
173
  searchClientTemplate,
163
174
  searchEndpointTemplate,
164
175
  stagedContentDir,
@@ -174,28 +185,35 @@ export type { PrerenderDepsPlugin } from "./render-deps.ts";
174
185
  const BLUME_SRC = join(packageRoot(), "src");
175
186
 
176
187
  /**
177
- * Absolute path to `babel-plugin-react-compiler`, resolved from Blume's own
178
- * package root (Blume ships it). Returns null when React or the compiler is off.
188
+ * Whether the generated `react()` call turns the React Compiler on: React and
189
+ * `react.compiler` are both on, and `oxc-transform-react` (Blume ships it)
190
+ * resolves. False when React or the compiler is off.
179
191
  *
180
- * The path must be absolute: @vitejs/plugin-react resolves babel plugins from
181
- * the *project* root, not `.blume/`, so a bare specifier fails in a user project
182
- * that never installed the plugin directly. Resolving from `packageRoot()` binds
183
- * to Blume's shipped copy regardless of the user's package manager or hoisting.
192
+ * The compiler is loaded by `@vitejs/plugin-react` with a bare
193
+ * `import("oxc-transform-react")` from its own directory, which fails the
194
+ * build when it throws, so the check walks the same chain — Blume →
195
+ * `@astrojs/react` → `@vitejs/plugin-react` — rather than resolving from
196
+ * Blume's root, which a strict package manager may not link the plugin to.
184
197
  */
185
198
  export const resolveReactCompiler = (
186
199
  config: ResolvedConfig,
187
200
  needsReact: boolean,
188
201
  pkgDir: string = packageRoot()
189
- ): string | null => {
202
+ ): boolean => {
190
203
  if (!(needsReact && config.react.compiler)) {
191
- return null;
204
+ return false;
192
205
  }
193
206
  try {
194
- return createRequire(pathToFileURL(join(pkgDir, "_.js")).href).resolve(
195
- "babel-plugin-react-compiler"
207
+ const astroReact = createRequire(
208
+ pathToFileURL(join(pkgDir, "_.js")).href
209
+ ).resolve("@astrojs/react");
210
+ const pluginReact = createRequire(astroReact).resolve(
211
+ "@vitejs/plugin-react"
196
212
  );
213
+ createRequire(pluginReact).resolve("oxc-transform-react");
214
+ return true;
197
215
  } catch {
198
- return null;
216
+ return false;
199
217
  }
200
218
  };
201
219
 
@@ -207,11 +225,11 @@ export const resolveReactCompiler = (
207
225
  export const reactCompilerWarnings = (
208
226
  config: ResolvedConfig,
209
227
  needsReact: boolean,
210
- compilerPath: string | null
228
+ compiler: boolean
211
229
  ): string[] =>
212
- needsReact && config.react.compiler && !compilerPath
230
+ needsReact && config.react.compiler && !compiler
213
231
  ? [
214
- "React Compiler is enabled but `babel-plugin-react-compiler` could not be resolved; falling back to an uncompiled build. Reinstall Blume, or set `react: { compiler: false }` to silence this.",
232
+ "React Compiler is enabled but `oxc-transform-react` could not be resolved; falling back to an uncompiled build. Reinstall Blume, or set `react: { compiler: false }` to silence this.",
215
233
  ]
216
234
  : [];
217
235
 
@@ -749,12 +767,12 @@ const isStringShorthand = <T>(value: T | string): value is string =>
749
767
  typeof value === "string";
750
768
 
751
769
  /**
752
- * The URL behind the header's repo mark. A string is used as-is: `github`
753
- * drives the per-page edit link, the header mark and the manifest's
770
+ * The URL behind the footer's repo mark. A string is used as-is: `github`
771
+ * drives the per-page edit link, the footer mark and the manifest's
754
772
  * `repository` together, so a project whose docs repo is private has to unset
755
773
  * all three, and would otherwise have no way to point the mark at anything.
756
774
  */
757
- const headerRepoUrl = (
775
+ const footerRepoUrl = (
758
776
  repo: boolean | string,
759
777
  derived: string | null
760
778
  ): string | null => {
@@ -961,11 +979,53 @@ const resolveBanner = (config: ResolvedConfig): BlumeBanner | null => {
961
979
  return {
962
980
  content: banner.content,
963
981
  dismissible: banner.dismissible,
964
- key: banner.id ?? banner.content,
982
+ key:
983
+ banner.id ??
984
+ resolveLocalizable(banner.content, undefined, config.i18n?.defaultLocale),
965
985
  link: banner.link,
966
986
  };
967
987
  };
968
988
 
989
+ /** The URL the built-in proxy is injected at (see {@link planPlaygroundProxy}). */
990
+ export const playgroundProxyPattern = (config: ResolvedConfig): string =>
991
+ withBasePath(config.basePath, "/_api-proxy");
992
+
993
+ /**
994
+ * The hand-written endpoint defaults for the runtime, the playground's
995
+ * `proxy: true` resolved to the built-in route's URL, as an OpenAPI
996
+ * reference's is.
997
+ */
998
+ const resolveApiPages = (config: ResolvedConfig): BlumeDataConfig["api"] => {
999
+ const { auth, playground, server } = config.api;
1000
+ const resolved: BlumeDataConfig["api"] = {
1001
+ playground: {
1002
+ enabled: playground.enabled,
1003
+ proxy:
1004
+ playground.proxy === true
1005
+ ? playgroundProxyPattern(config)
1006
+ : playground.proxy,
1007
+ },
1008
+ };
1009
+ if (auth) {
1010
+ resolved.auth = auth;
1011
+ }
1012
+ if (server) {
1013
+ resolved.server = server;
1014
+ }
1015
+ return resolved;
1016
+ };
1017
+
1018
+ /** The footer config for the runtime: `null` when unset or empty, so no bare border renders. */
1019
+ const resolveFooter = (
1020
+ config: ResolvedConfig
1021
+ ): ResolvedConfig["footer"] | null => {
1022
+ const { footer } = config;
1023
+ return footer &&
1024
+ (footer.links.length > 0 || Object.keys(footer.socials).length > 0)
1025
+ ? footer
1026
+ : null;
1027
+ };
1028
+
969
1029
  /**
970
1030
  * The OG card's brand mark: a `seo.og.logo` of `false` opts out of any mark,
971
1031
  * a configured SVG wins over the site logo, and a non-SVG value resolves to
@@ -1036,6 +1096,22 @@ const resolveGithubData = (
1036
1096
  }
1037
1097
  : null;
1038
1098
 
1099
+ /** The assistant's snapshot: what the panel needs, never a secret. */
1100
+ const resolveAssistant = (
1101
+ config: ResolvedConfig
1102
+ ): BlumeDataConfig["assistant"] => {
1103
+ const { assistant } = config.ai;
1104
+ if (!assistant?.enabled) {
1105
+ return null;
1106
+ }
1107
+ return {
1108
+ captcha: assistant.captcha ? captchaSettings(assistant.captcha) : null,
1109
+ endpoint: assistant.endpoint ?? null,
1110
+ suggestions: assistant.suggestions,
1111
+ support: assistant.support ?? null,
1112
+ };
1113
+ };
1114
+
1039
1115
  /** Serialize the content graph into the data module the runtime consumes. */
1040
1116
  export const buildRuntimeData = (project: BlumeProject): string => {
1041
1117
  const { config, context, graph, manifest } = project;
@@ -1067,10 +1143,10 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1067
1143
 
1068
1144
  const { i18n } = config;
1069
1145
 
1070
- // Resolve the header repo link per locale. API references no longer add a tab
1146
+ // Resolve the footer's repo link per locale. API references no longer add a tab
1071
1147
  // automatically — authors point a `navigation.tabs` entry at the reference
1072
1148
  // route to surface it (see `referenceRoutes`).
1073
- const markUrl = headerRepoUrl(config.navigation.repo, repoUrl);
1149
+ const markUrl = footerRepoUrl(config.navigation.repo, repoUrl);
1074
1150
  const withRepoUrl = (nav: Navigation): Navigation => ({
1075
1151
  ...nav,
1076
1152
  repoUrl: markUrl,
@@ -1078,23 +1154,32 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1078
1154
 
1079
1155
  // Resolved UI dictionaries: one per locale under i18n, English baseline
1080
1156
  // otherwise. Threaded into chrome so the catch-all can pick the active locale.
1157
+ // The `changelog` config's title and description replace the dictionaries'.
1081
1158
  const uiByLocale = i18n
1082
1159
  ? Object.fromEntries(
1083
1160
  i18n.locales.map(({ code }) => [
1084
1161
  code,
1085
- resolveUIStrings(code, {
1086
- defaultLocale: i18n.defaultLocale,
1087
- overrides: i18n.ui,
1088
- }),
1162
+ withChangelogIndexText(
1163
+ config,
1164
+ resolveUIStrings(code, {
1165
+ defaultLocale: i18n.defaultLocale,
1166
+ overrides: i18n.ui,
1167
+ }),
1168
+ code
1169
+ ),
1089
1170
  ])
1090
1171
  )
1091
1172
  : {};
1092
- const defaultUi = i18n
1093
- ? resolveUIStrings(i18n.defaultLocale, {
1094
- defaultLocale: i18n.defaultLocale,
1095
- overrides: i18n.ui,
1096
- })
1097
- : EN_UI;
1173
+ const defaultUi = withChangelogIndexText(
1174
+ config,
1175
+ i18n
1176
+ ? resolveUIStrings(i18n.defaultLocale, {
1177
+ defaultLocale: i18n.defaultLocale,
1178
+ overrides: i18n.ui,
1179
+ })
1180
+ : EN_UI,
1181
+ i18n?.defaultLocale
1182
+ );
1098
1183
 
1099
1184
  const navigationByLocale = i18n
1100
1185
  ? Object.fromEntries(
@@ -1117,17 +1202,14 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1117
1202
  const data: BlumeData = {
1118
1203
  config: {
1119
1204
  analytics: config.analytics,
1205
+ api: resolveApiPages(config),
1120
1206
  appleIcon: resolveAppleIcon(project),
1121
- assistant: config.ai.assistant?.enabled
1122
- ? {
1123
- endpoint: config.ai.assistant.endpoint ?? null,
1124
- suggestions: config.ai.assistant.suggestions,
1125
- }
1126
- : null,
1207
+ assistant: resolveAssistant(config),
1127
1208
  banner: resolveBanner(config),
1128
1209
  basePath: config.basePath,
1129
1210
  codeThemes: config.markdown.code.theme,
1130
1211
  codeWrap: config.markdown.code.wrap,
1212
+ consent: config.consent,
1131
1213
  dateFormat: config.dateFormat,
1132
1214
  description: config.description,
1133
1215
  discovery: {
@@ -1139,7 +1221,9 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1139
1221
  sitemap: config.seo.sitemap && Boolean(config.deployment.options.site),
1140
1222
  },
1141
1223
  favicon: resolveFavicon(project),
1142
- feedback: config.feedback,
1224
+ feedback: config.feedback.enabled,
1225
+ feedbackComments: config.feedback.comments,
1226
+ footer: resolveFooter(config),
1143
1227
  github: resolveGithubData(github),
1144
1228
  i18n: i18n
1145
1229
  ? {
@@ -1153,6 +1237,7 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1153
1237
  dir,
1154
1238
  label,
1155
1239
  })),
1240
+ routeByBrowserLanguage: i18n.routeByBrowserLanguage,
1156
1241
  }
1157
1242
  : null,
1158
1243
  // `undefined` members drop out of the JSON snapshot; the null keeps the
@@ -1172,6 +1257,10 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1172
1257
  route: config.agents.mcp.route,
1173
1258
  }
1174
1259
  : null,
1260
+ metatags: config.seo.metatags ?? null,
1261
+ narration: config.narration.enabled
1262
+ ? { generated: config.narration.provider !== null }
1263
+ : null,
1175
1264
  // `og.enabled` is resolved to a definite boolean in `loadConfig`; coerce
1176
1265
  // the optional schema type so the serialized shape stays `boolean`.
1177
1266
  // Card fonts are baked into the generated OG endpoint (they can carry
@@ -1187,6 +1276,7 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1187
1276
  openInChat: config.ai.openInChat,
1188
1277
  repoUrl,
1189
1278
  search: {
1279
+ analytics: config.search.analytics,
1190
1280
  enabled: config.search.provider.mode !== "none",
1191
1281
  popular: resolveSearchPopular(config.search.popular, config.basePath),
1192
1282
  provider: config.search.provider.kind,
@@ -1496,10 +1586,6 @@ const writeApiFiles = async (
1496
1586
  /** The proxy endpoint's file under the Astro `src/` dir (eject writes it too). */
1497
1587
  export const PLAYGROUND_PROXY_ENTRY = join("blume-openapi", "api-proxy.ts");
1498
1588
 
1499
- /** The URL the built-in proxy is injected at (see {@link planPlaygroundProxy}). */
1500
- export const playgroundProxyPattern = (config: ResolvedConfig): string =>
1501
- withBasePath(config.basePath, "/_api-proxy");
1502
-
1503
1589
  /**
1504
1590
  * Decide whether to generate the playground's built-in CORS proxy endpoint.
1505
1591
  * Only the Blume renderer's playground with `proxy: true` needs it — a proxy
@@ -1592,6 +1678,47 @@ type DocumentPathItem = { servers?: DocumentServer[] } & Partial<
1592
1678
  export const specOrigins = (data: OpenApiData): string[] =>
1593
1679
  [...new Set(Object.values(data).flatMap(specOriginsOf))].toSorted();
1594
1680
 
1681
+ /** The origin of an absolute URL, or `null` for a path or anything unparsable. */
1682
+ const originOf = (url: string): string | null => {
1683
+ try {
1684
+ return new URL(url).origin;
1685
+ } catch {
1686
+ return null;
1687
+ }
1688
+ };
1689
+
1690
+ /**
1691
+ * The origins hand-written endpoint pages send to through the built-in
1692
+ * proxy: the site's `api.server`, and every page whose `api` names a full
1693
+ * URL. Empty unless those pages use the built-in proxy.
1694
+ */
1695
+ export const apiPageOrigins = (project: BlumeProject): string[] => {
1696
+ const { config } = project;
1697
+ if (!apiPagesUseBuiltinProxy(config)) {
1698
+ return [];
1699
+ }
1700
+ const targets = project.graph.pages.map(
1701
+ (page) => parseApiEndpoint(page.meta.api ?? "")?.target ?? ""
1702
+ );
1703
+ return [config.api.server ?? "", ...targets].flatMap((target) => {
1704
+ const origin = originOf(target);
1705
+ return origin ? [origin] : [];
1706
+ });
1707
+ };
1708
+
1709
+ /**
1710
+ * A warning when the hand-written endpoint pages send through the built-in
1711
+ * proxy but name no absolute origin for it to allow, so it would refuse every
1712
+ * request they send.
1713
+ */
1714
+ export const apiPageProxyWarnings = (project: BlumeProject): string[] =>
1715
+ apiPagesUseBuiltinProxy(project.config) &&
1716
+ apiPageOrigins(project).length === 0
1717
+ ? [
1718
+ "api.playground.proxy is true, but api.server isn't an absolute URL and no page's api frontmatter names one, so the built-in proxy has no origin to allow and will refuse every request the endpoint pages send. Set api.server to the API's URL, like https://api.acme.com/v1.",
1719
+ ]
1720
+ : [];
1721
+
1595
1722
  /**
1596
1723
  * Build-time diagnostics for playground sends the built-in proxy would refuse.
1597
1724
  * The baked-in allowlist pools every documented origin, but each spec's
@@ -1644,9 +1771,12 @@ const writeAskFiles = async (
1644
1771
  await write(
1645
1772
  join(srcDir, "pages", "api", "ask.ts"),
1646
1773
  askEndpointTemplate(backend, {
1774
+ captcha: assistant.captcha,
1647
1775
  cors: assistant.cors,
1648
1776
  instructions: assistant.instructions,
1777
+ rateLimit: project.config.rateLimit,
1649
1778
  retrieval: assistant.retrieval,
1779
+ tools: assistant.tools ?? backend.toolsByDefault,
1650
1780
  })
1651
1781
  );
1652
1782
  };
@@ -1863,6 +1993,7 @@ export const generateRuntime = async (
1863
1993
  const askPath = join(srcDir, "generated", "Ask.astro");
1864
1994
  const themePath = join(srcDir, "generated", "app.css");
1865
1995
  const searchClientPath = join(srcDir, "generated", "search-client.ts");
1996
+ const consentClientPath = join(srcDir, "generated", "consent-client.ts");
1866
1997
  const featuresPath = join(srcDir, "generated", "features.ts");
1867
1998
  const examplesPath = join(srcDir, "generated", "examples.ts");
1868
1999
  const examplesThemePath = join(srcDir, "generated", "examples.css");
@@ -1955,11 +2086,12 @@ export const generateRuntime = async (
1955
2086
  const needsVue = frameworks.has("vue");
1956
2087
  const needsSvelte = frameworks.has("svelte");
1957
2088
 
1958
- // Absolute path to the React Compiler babel plugin (null when off). Resolved
1959
- // here, Node-side, so the generated config points babel straight at Blume's
1960
- // shipped copy — see resolveReactCompiler. Any unresolved-but-requested
1961
- // warning is folded into `warnings` below (declared later).
1962
- const reactCompilerPath = resolveReactCompiler(config, needsReact);
2089
+ // Whether react() turns the React Compiler on (false when off). Checked here,
2090
+ // Node-side, so an unresolvable compiler degrades to an uncompiled build
2091
+ // instead of failing it — see resolveReactCompiler. Any
2092
+ // unresolved-but-requested warning is folded into `warnings` below (declared
2093
+ // later).
2094
+ const reactCompiler = resolveReactCompiler(config, needsReact);
1963
2095
 
1964
2096
  // Custom pages that should get a generated OG card (the home most of all).
1965
2097
  // Computed before the MCP `.well-known` routes are appended below — those are
@@ -2000,7 +2132,9 @@ export const generateRuntime = async (
2000
2132
  // Computed once: the endpoint template bakes it in below. A spec that
2001
2133
  // contributes no origin of its own gets a per-spec diagnostic
2002
2134
  // (`proxyAllowlistWarnings`) — the proxy would refuse its every send.
2003
- const proxyOrigins = specOrigins(openApiData);
2135
+ const proxyOrigins = [
2136
+ ...new Set([...specOrigins(openApiData), ...apiPageOrigins(project)]),
2137
+ ].toSorted();
2004
2138
 
2005
2139
  const hasStaged = staged.size > 0;
2006
2140
  // Only emit a project-scanning `docs` collection when a filesystem source
@@ -2022,6 +2156,7 @@ export const generateRuntime = async (
2022
2156
  aliases: resolveTsconfigAliases(context.root),
2023
2157
  askPath,
2024
2158
  config,
2159
+ consentClientPath,
2025
2160
  contentRoot: docsCollection.base,
2026
2161
  contentRoutes,
2027
2162
  context,
@@ -2034,7 +2169,7 @@ export const generateRuntime = async (
2034
2169
  needsSvelte,
2035
2170
  needsVue,
2036
2171
  pages,
2037
- reactCompilerPath,
2172
+ reactCompiler,
2038
2173
  searchClientPath,
2039
2174
  themePath,
2040
2175
  })
@@ -2097,7 +2232,7 @@ export const generateRuntime = async (
2097
2232
  languageIcons,
2098
2233
  sources: [
2099
2234
  `${BLUME_SRC}/**/*.{astro,ts,tsx}`,
2100
- `${context.root}/**/*.{astro,mdx,ts,tsx}`,
2235
+ `${context.root}/**/*.{astro,jsx,mdx,ts,tsx}`,
2101
2236
  ],
2102
2237
  twoslashCss: twoslashCss(),
2103
2238
  userTheme,
@@ -2135,7 +2270,10 @@ export const generateRuntime = async (
2135
2270
  writeMcpFiles(mcp, write, agentData),
2136
2271
  writeApiFiles(project, api, write, agentData, mcp),
2137
2272
  playgroundProxy.enabled
2138
- ? write(playgroundProxy.entrypoint, playgroundProxyTemplate(proxyOrigins))
2273
+ ? write(
2274
+ playgroundProxy.entrypoint,
2275
+ playgroundProxyTemplate(proxyOrigins, config.rateLimit)
2276
+ )
2139
2277
  : Promise.resolve(false),
2140
2278
  ]);
2141
2279
 
@@ -2186,6 +2324,7 @@ export const generateRuntime = async (
2186
2324
  }),
2187
2325
  writeNotFoundPage(write, srcDir, pages, project.graph.pages),
2188
2326
  write(searchClientPath, searchClientTemplate(config)),
2327
+ write(consentClientPath, consentClientTemplate(config.consent)),
2189
2328
  write(featuresPath, featuresTemplate(clientFeatures)),
2190
2329
  ]);
2191
2330
 
@@ -2204,7 +2343,11 @@ export const generateRuntime = async (
2204
2343
  if (searchAdapter.kind === "mixedbread") {
2205
2344
  await write(
2206
2345
  join(srcDir, "pages", "api", "search.ts"),
2207
- mixedbreadSearchEndpointTemplate(searchAdapter.options)
2346
+ mixedbreadSearchEndpointTemplate(
2347
+ searchAdapter.options,
2348
+ sourcePages(project),
2349
+ config.rateLimit
2350
+ )
2208
2351
  );
2209
2352
  }
2210
2353
 
@@ -2258,7 +2401,8 @@ export const generateRuntime = async (
2258
2401
  const warnings: string[] = [
2259
2402
  ...(depsLinkWarning ? [depsLinkWarning] : []),
2260
2403
  ...proxyAllowlistWarnings(config, openApiData),
2261
- ...reactCompilerWarnings(config, needsReact, reactCompilerPath),
2404
+ ...apiPageProxyWarnings(project),
2405
+ ...reactCompilerWarnings(config, needsReact, reactCompiler),
2262
2406
  ...mcp.warnings,
2263
2407
  ...islandDiscovery.warnings,
2264
2408
  ...exampleDiscovery.warnings,
@@ -2266,24 +2410,18 @@ export const generateRuntime = async (
2266
2410
  ...overrideWarnings,
2267
2411
  ];
2268
2412
 
2269
- // Missing-navigation-target check, now that every servable route is known:
2270
- // content routes, custom `.astro` pages, the generated changelog, and any
2271
- // OpenAPI reference routes (so a tab an author points at one still validates).
2272
- const navTargetRoutes = new Set<string>([
2273
- ...project.graph.routes.keys(),
2274
- ...pages.map((page) => page.pattern),
2275
- ...referenceRoutes(config),
2276
- ]);
2277
- if (changelogIndex) {
2278
- navTargetRoutes.add("/changelog");
2279
- }
2413
+ // Missing-navigation-target check, now that every servable route is known
2414
+ // (see `navTargetRoutes`).
2280
2415
  // Curated `search.popular` icons live outside the navigation model, so they
2281
2416
  // miss `validateNavIcons` in the graph build — they're checked here too,
2282
2417
  // where the search config is known. A typo otherwise just renders the
2283
2418
  // default glyph.
2284
2419
  warnings.push(
2285
2420
  ...[
2286
- ...validateNavTargets(project.graph.navigation, navTargetRoutes),
2421
+ ...validateNavTargets(
2422
+ project.graph.navigation,
2423
+ navTargetRoutes(project, pages)
2424
+ ),
2287
2425
  ...validateSearchPopularIcons(config.search.popular),
2288
2426
  ].map(diagnosticWarning)
2289
2427
  );
@@ -2300,6 +2438,12 @@ export const generateRuntime = async (
2300
2438
  knownComponentTags,
2301
2439
  new Set(registry.map((item) => item.name))
2302
2440
  ).map(diagnosticWarning),
2441
+ ...missingExampleDiagnostics(
2442
+ project.graph.pages,
2443
+ exampleDiscovery,
2444
+ context.root,
2445
+ knownComponentTags
2446
+ ).map(diagnosticWarning),
2303
2447
  ...dependencyWarnings
2304
2448
  );
2305
2449
  if (hasScalarReferences(config)) {
@@ -2,6 +2,7 @@ export { withAdapterRoot } from "./adapter-root.ts";
2
2
  export { generateRuntime, prerenderDepsPlugin } from "./generate.ts";
3
3
  export { includeHmrPlugin } from "./include-hmr.ts";
4
4
  export { withIncludeRefresh } from "./include-refresh.ts";
5
+ export { variablesVitePlugin } from "./variables.ts";
5
6
  export type { GenerateResult } from "./generate.ts";
6
7
  export {
7
8
  blumeIntegration,
@@ -9,6 +9,11 @@ import type { CustomPageRoute } from "../core/custom-pages.ts";
9
9
  import { enrichDiagnostic } from "../core/diagnostics.ts";
10
10
  import { scanProject } from "../core/project-graph.ts";
11
11
  import type { BlumeProject } from "../core/project-graph.ts";
12
+ import {
13
+ matchCompiledRedirect,
14
+ requestPath,
15
+ } from "../core/redirect-patterns.ts";
16
+ import type { CompiledRedirect } from "../core/redirect-patterns.ts";
12
17
  import type { Diagnostic } from "../core/types.ts";
13
18
  import { publishBuildArtifacts } from "../deploy/artifacts.ts";
14
19
  import type { ArtifactLogger } from "../deploy/artifacts.ts";
@@ -336,6 +341,14 @@ export interface BlumeIntegrationOptions {
336
341
  * its already-scanned project instead.
337
342
  */
338
343
  buildArtifactsRoot?: string;
344
+ /**
345
+ * Every configured redirect, compiled against base-less request paths
346
+ * (see `compileEveryRedirect`), for the dev server to answer itself.
347
+ * Astro's own `redirects` carry only the exact ones, since it can't
348
+ * prerender a pattern's pages, and its dev handler answers one whose
349
+ * destination `[...slug]` serves with a `301` whatever its status.
350
+ */
351
+ redirects?: CompiledRedirect[];
339
352
  }
340
353
 
341
354
  /**
@@ -386,10 +399,12 @@ const negotiateMarkdown =
386
399
  if (homeLinkHeader && isHomeUrl(req.url)) {
387
400
  res.setHeader("Link", homeLinkHeader);
388
401
  }
389
- if (prefersMarkdown(req.headers.accept)) {
390
- const variant = markdownVariantUrl(req.url, contentRoutes);
391
- if (variant) {
392
- res.setHeader("Vary", "Accept");
402
+ const variant = markdownVariantUrl(req.url, contentRoutes);
403
+ if (variant) {
404
+ // Both answers at a negotiated URL depend on `Accept`, the HTML one
405
+ // too, so a cache never hands one client's variant to the other.
406
+ res.setHeader("Vary", "Accept");
407
+ if (prefersMarkdown(req.headers.accept)) {
393
408
  req.url = variant;
394
409
  }
395
410
  }
@@ -397,6 +412,23 @@ const negotiateMarkdown =
397
412
  next();
398
413
  };
399
414
 
415
+ /**
416
+ * Answer a configured redirect in dev with its status, the way the server
417
+ * wrappers do in a build. Request URLs arrive base-less (see
418
+ * {@link negotiateMarkdown}), and the redirects were based to match.
419
+ */
420
+ const answerRedirects =
421
+ (redirects: readonly CompiledRedirect[]) =>
422
+ (req: IncomingMessage, res: ServerResponse, next: () => void): void => {
423
+ const answer = matchCompiledRedirect(redirects, requestPath(req.url ?? ""));
424
+ if (!answer) {
425
+ next();
426
+ return;
427
+ }
428
+ res.writeHead(answer[1], { Location: answer[0] });
429
+ res.end();
430
+ };
431
+
400
432
  /** The `.d.ts` the integration injects for the `blume:*` virtual modules. */
401
433
  const MODULE_TYPES_FILE = "modules.d.ts";
402
434
 
@@ -502,6 +534,12 @@ export const blumeIntegration = (
502
534
  }),
503
535
  route: "",
504
536
  });
537
+ if (options.redirects) {
538
+ server.middlewares.stack.unshift({
539
+ handle: answerRedirects(options.redirects),
540
+ route: "",
541
+ });
542
+ }
505
543
  },
506
544
  },
507
545
  name: "blume",
@@ -8,6 +8,9 @@
8
8
  * helpers (`deploy/cloudflare-negotiation.ts` — its deploy bundle is uploaded
9
9
  * unbundled, so it cannot import this module); when editing here, mirror the
10
10
  * change there. Parity is enforced by `test/cloudflare-negotiation.test.ts`.
11
+ * Vercel's routing conditions (`deploy/vercel-negotiation.ts`) spell the same
12
+ * rule as regexes, checked against {@link prefersMarkdown} by
13
+ * `test/vercel-negotiation.test.ts`.
11
14
  */
12
15
 
13
16
  interface AcceptEntry {
@@ -75,8 +75,16 @@ declare module "blume:features" {
75
75
  | null;
76
76
  }
77
77
 
78
+ declare module "blume:consent-client" {
79
+ export const startConsentClient: (
80
+ consent: import("blume/components/layout/consent/types.ts").BlumeConsent
81
+ ) => void;
82
+ }
83
+
78
84
  declare module "blume:search-client" {
79
- export const createSearch: () =>
85
+ export const createSearch: (
86
+ options?: import("blume/components/layout/search/types.ts").SearchClientOptions
87
+ ) =>
80
88
  | import("blume/components/layout/search/types.ts").SearchFn
81
89
  | Promise<import("blume/components/layout/search/types.ts").SearchFn>;
82
90
  }