blume 2.0.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +48 -0
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-1d7ve1dm.js → chunk-0gz36akr.js} +18 -2
  5. package/dist/cli/{chunk-1d7ve1dm.js.map → chunk-0gz36akr.js.map} +3 -3
  6. package/dist/cli/{chunk-2eytanqx.js → chunk-1n228xqb.js} +2 -2
  7. package/dist/cli/{chunk-yfyb25rh.js → chunk-2f3ndkpw.js} +24 -8
  8. package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
  9. package/dist/cli/{chunk-r20tn01b.js → chunk-2f7n4qzt.js} +8 -2
  10. package/dist/cli/{chunk-r20tn01b.js.map → chunk-2f7n4qzt.js.map} +3 -3
  11. package/dist/cli/{chunk-35d4wj9f.js → chunk-2n4ps1b3.js} +7 -7
  12. package/dist/cli/{chunk-j85vccga.js → chunk-43zcf4gz.js} +97 -57
  13. package/dist/cli/{chunk-j85vccga.js.map → chunk-43zcf4gz.js.map} +6 -6
  14. package/dist/cli/{chunk-e04dxsz1.js → chunk-4ejxbzee.js} +1 -1
  15. package/dist/cli/{chunk-5m5nmvyq.js → chunk-4h8z9vv5.js} +233 -39
  16. package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
  17. package/dist/cli/{chunk-5f86nr5m.js → chunk-5cg2rzgf.js} +18 -16
  18. package/dist/cli/{chunk-5f86nr5m.js.map → chunk-5cg2rzgf.js.map} +2 -2
  19. package/dist/cli/{chunk-tzmab476.js → chunk-5ffywsmb.js} +4 -4
  20. package/dist/cli/{chunk-2z928egk.js → chunk-5wj2qwn2.js} +5 -5
  21. package/dist/cli/chunk-6bm0xpgd.js +18 -0
  22. package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
  23. package/dist/cli/{chunk-vg9r4eb9.js → chunk-713mngdq.js} +12 -5
  24. package/dist/cli/{chunk-vg9r4eb9.js.map → chunk-713mngdq.js.map} +3 -3
  25. package/dist/cli/{chunk-5xvm6tfj.js → chunk-9geymqns.js} +17 -15
  26. package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-9geymqns.js.map} +2 -2
  27. package/dist/cli/{chunk-q58y5e6a.js → chunk-9xr4dgee.js} +26 -17
  28. package/dist/cli/chunk-9xr4dgee.js.map +10 -0
  29. package/dist/cli/{chunk-b07cmahc.js → chunk-amrb6hgh.js} +2 -2
  30. package/dist/cli/chunk-cm89scdv.js +443 -0
  31. package/dist/cli/chunk-cm89scdv.js.map +11 -0
  32. package/dist/cli/{chunk-akbpwfxc.js → chunk-cmtcnh9f.js} +2 -2
  33. package/dist/cli/chunk-cy5bm0j0.js +104 -0
  34. package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
  35. package/dist/cli/{chunk-crgn1q09.js → chunk-e7vvk5ya.js} +4 -4
  36. package/dist/cli/{chunk-pehfxfta.js → chunk-g2z9x01v.js} +6 -98
  37. package/dist/cli/chunk-g2z9x01v.js.map +10 -0
  38. package/dist/cli/{chunk-tkacnehg.js → chunk-gp84za0h.js} +2 -2
  39. package/dist/cli/{chunk-wrr3j9w9.js → chunk-h2a48yhd.js} +186 -63
  40. package/dist/cli/chunk-h2a48yhd.js.map +36 -0
  41. package/dist/cli/{chunk-hm3vjy5s.js → chunk-jnwj5kjj.js} +14 -9
  42. package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-jnwj5kjj.js.map} +4 -4
  43. package/dist/cli/chunk-kwrg63tm.js +31 -0
  44. package/dist/cli/chunk-kwrg63tm.js.map +10 -0
  45. package/dist/cli/{chunk-2hsdwb9n.js → chunk-nd1821sk.js} +18 -16
  46. package/dist/cli/{chunk-2hsdwb9n.js.map → chunk-nd1821sk.js.map} +2 -2
  47. package/dist/cli/{chunk-6dsbexzp.js → chunk-ntv4qrt7.js} +17 -15
  48. package/dist/cli/{chunk-6dsbexzp.js.map → chunk-ntv4qrt7.js.map} +2 -2
  49. package/dist/cli/{chunk-r9rcc4w7.js → chunk-p804f3pe.js} +7 -7
  50. package/dist/cli/{chunk-ey84smr6.js → chunk-py62fewh.js} +6 -6
  51. package/dist/cli/{chunk-ey84smr6.js.map → chunk-py62fewh.js.map} +1 -1
  52. package/dist/cli/chunk-q3wxxq39.js +126 -0
  53. package/dist/cli/chunk-q3wxxq39.js.map +11 -0
  54. package/dist/cli/{chunk-9t7a85s3.js → chunk-rekqz4qg.js} +23 -13
  55. package/dist/cli/chunk-rekqz4qg.js.map +10 -0
  56. package/dist/cli/{chunk-8ktnccpt.js → chunk-ta27feev.js} +1 -1
  57. package/dist/cli/{chunk-pv29h0wf.js → chunk-xkz5xbtv.js} +3476 -822
  58. package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
  59. package/dist/cli/{chunk-a58773jm.js → chunk-y4ykbark.js} +2 -2
  60. package/dist/cli/{chunk-p3v96n38.js → chunk-y5h4r2y0.js} +4 -4
  61. package/dist/cli/{chunk-acanzt5p.js → chunk-yj17vs39.js} +6 -6
  62. package/dist/cli/{chunk-p73c0m7w.js → chunk-yxmk4pec.js} +16 -14
  63. package/dist/cli/{chunk-p73c0m7w.js.map → chunk-yxmk4pec.js.map} +2 -2
  64. package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
  65. package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
  66. package/dist/cli/{chunk-c8chx29p.js → chunk-zf748avv.js} +384 -207
  67. package/dist/cli/chunk-zf748avv.js.map +37 -0
  68. package/dist/cli/{chunk-g4hq16wv.js → chunk-zhvd6adm.js} +16 -14
  69. package/dist/cli/{chunk-g4hq16wv.js.map → chunk-zhvd6adm.js.map} +2 -2
  70. package/dist/cli/index.js +26 -20
  71. package/dist/cli/index.js.map +5 -5
  72. package/dist/types/ai/agent-surface.d.ts +8 -7
  73. package/dist/types/ai/ai-catalog.d.ts +7 -0
  74. package/dist/types/ai/ask-context.d.ts +22 -0
  75. package/dist/types/ai/ask.d.ts +271 -58
  76. package/dist/types/ai/index.d.ts +2 -2
  77. package/dist/types/ai/site-skill.d.ts +26 -0
  78. package/dist/types/ai/skills.d.ts +16 -0
  79. package/dist/types/astro/integration.d.ts +8 -0
  80. package/dist/types/captcha/hcaptcha.d.ts +27 -0
  81. package/dist/types/captcha/index.d.ts +28 -0
  82. package/dist/types/captcha/schema.d.ts +29 -0
  83. package/dist/types/captcha/turnstile.d.ts +28 -0
  84. package/dist/types/components/content/api-field.d.ts +59 -0
  85. package/dist/types/components/content/api-page.d.ts +95 -0
  86. package/dist/types/components/layout/nav-utils.d.ts +26 -0
  87. package/dist/types/components/openapi/helpers.d.ts +137 -0
  88. package/dist/types/components/openapi/security.d.ts +85 -0
  89. package/dist/types/consent/ethyca.d.ts +48 -0
  90. package/dist/types/consent/index.d.ts +37 -0
  91. package/dist/types/consent/native.d.ts +28 -0
  92. package/dist/types/consent/osano.d.ts +42 -0
  93. package/dist/types/consent/schema.d.ts +110 -0
  94. package/dist/types/core/config-input.d.ts +187 -20
  95. package/dist/types/core/data.d.ts +49 -4
  96. package/dist/types/core/footer.d.ts +8 -0
  97. package/dist/types/core/i18n-ui.d.ts +86 -0
  98. package/dist/types/core/includes.d.ts +8 -2
  99. package/dist/types/core/localizable.d.ts +7 -0
  100. package/dist/types/core/page-modes.d.ts +29 -0
  101. package/dist/types/core/redirect-patterns.d.ts +144 -0
  102. package/dist/types/core/related.d.ts +40 -0
  103. package/dist/types/core/schema.d.ts +551 -56
  104. package/dist/types/core/sources/read.d.ts +5 -0
  105. package/dist/types/core/types.d.ts +1 -1
  106. package/dist/types/core/variables.d.ts +42 -0
  107. package/dist/types/deploy/node-headers.d.ts +13 -2
  108. package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
  109. package/dist/types/deploy/platforms/netlify.d.ts +7 -0
  110. package/dist/types/deploy/platforms/vercel.d.ts +6 -0
  111. package/dist/types/deploy/redirects.d.ts +39 -11
  112. package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
  113. package/dist/types/markdown/code-title.d.ts +17 -0
  114. package/dist/types/markdown/features.d.ts +3 -2
  115. package/dist/types/narration/build.d.ts +70 -0
  116. package/dist/types/narration/provider.d.ts +26 -0
  117. package/dist/types/narration/script.d.ts +154 -0
  118. package/dist/types/openapi/model.d.ts +12 -6
  119. package/dist/types/openapi/overlay.d.ts +54 -0
  120. package/dist/types/openapi/parse.d.ts +13 -0
  121. package/dist/types/openapi/references.d.ts +14 -4
  122. package/dist/types/ratelimit/cloudflare.d.ts +39 -0
  123. package/dist/types/ratelimit/index.d.ts +27 -0
  124. package/dist/types/ratelimit/memory.d.ts +36 -0
  125. package/dist/types/ratelimit/schema.d.ts +111 -0
  126. package/dist/types/ratelimit/upstash.d.ts +21 -0
  127. package/dist/types/ratelimit/wrangler.d.ts +23 -0
  128. package/dist/types/reference/asyncapi.d.ts +10 -10
  129. package/dist/types/reference/graphql.d.ts +13 -10
  130. package/dist/types/reference/openapi.d.ts +33 -12
  131. package/dist/types/reference/options.d.ts +45 -5
  132. package/dist/types/reference/scalar.d.ts +13 -0
  133. package/dist/types/reference/schema.d.ts +60 -36
  134. package/dist/types/search/documents.d.ts +12 -1
  135. package/dist/types/search/orama-index.d.ts +4 -0
  136. package/dist/types/seo/metatags.d.ts +20 -0
  137. package/docs/02-deployment.mdx +41 -5
  138. package/docs/03-upgrading.mdx +4 -4
  139. package/docs/04-migrating.mdx +1 -1
  140. package/docs/advanced/changelog.mdx +2 -2
  141. package/docs/advanced/skills.mdx +14 -0
  142. package/docs/cli/audit.mdx +21 -1
  143. package/docs/cli/index.mdx +1 -0
  144. package/docs/configuration/analytics.mdx +3 -1
  145. package/docs/configuration/assistant.mdx +188 -36
  146. package/docs/configuration/consent.mdx +100 -0
  147. package/docs/configuration/customization.mdx +4 -4
  148. package/docs/configuration/index.mdx +63 -5
  149. package/docs/configuration/meta.ts +3 -0
  150. package/docs/configuration/narration.mdx +119 -0
  151. package/docs/configuration/rate-limiting.mdx +69 -0
  152. package/docs/configuration/search.mdx +29 -1
  153. package/docs/configuration/theming.mdx +3 -1
  154. package/docs/content/components.mdx +106 -0
  155. package/docs/content/frontmatter.mdx +76 -0
  156. package/docs/content/i18n.mdx +38 -3
  157. package/docs/content/includes.mdx +16 -0
  158. package/docs/content/meta.mdx +1 -0
  159. package/docs/content/meta.ts +1 -0
  160. package/docs/content/navigation.mdx +28 -6
  161. package/docs/content/sources/contentful.mdx +32 -0
  162. package/docs/content/sources/custom.mdx +39 -0
  163. package/docs/content/sources/github-releases.mdx +31 -0
  164. package/docs/content/sources/index.mdx +91 -0
  165. package/docs/content/sources/meta.ts +16 -0
  166. package/docs/content/sources/notion.mdx +32 -0
  167. package/docs/content/sources/obsidian.mdx +37 -0
  168. package/docs/content/sources/payload.mdx +30 -0
  169. package/docs/content/sources/remote-mdx.mdx +40 -0
  170. package/docs/content/sources/sanity.mdx +29 -0
  171. package/docs/content/sources/strapi.mdx +31 -0
  172. package/docs/content/syntax.mdx +67 -2
  173. package/docs/content/variables.mdx +41 -0
  174. package/docs/discoverability/agent-discovery.mdx +29 -2
  175. package/docs/discoverability/index.mdx +1 -1
  176. package/docs/discoverability/llms-txt.mdx +1 -1
  177. package/docs/discoverability/metadata.mdx +17 -0
  178. package/docs/references/api-pages.mdx +74 -0
  179. package/docs/references/asyncapi.mdx +1 -1
  180. package/docs/references/graphql.mdx +2 -2
  181. package/docs/references/meta.ts +1 -1
  182. package/docs/references/openapi.mdx +102 -3
  183. package/docs/references/scalar.mdx +3 -1
  184. package/package.json +36 -1
  185. package/skills/blume/SKILL.md +3 -0
  186. package/skills/blume-migrate/SKILL.md +5 -5
  187. package/skills/blume-migrate/references/docusaurus.md +3 -3
  188. package/skills/blume-migrate/references/mintlify.md +37 -19
  189. package/skills/blume-migrate/references/nextra.md +2 -2
  190. package/skills/blume-migrate/references/starlight.md +2 -1
  191. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
  192. package/skills/blume-write-skill/SKILL.md +82 -0
  193. package/src/ai/agent-readability.ts +2 -1
  194. package/src/ai/agent-surface.ts +9 -7
  195. package/src/ai/ai-catalog.ts +6 -3
  196. package/src/ai/ask-context.ts +73 -20
  197. package/src/ai/ask-data.ts +6 -0
  198. package/src/ai/ask-tools.ts +142 -0
  199. package/src/ai/ask.ts +354 -76
  200. package/src/ai/component-markdown.ts +75 -0
  201. package/src/ai/cors.ts +2 -0
  202. package/src/ai/index.ts +12 -0
  203. package/src/ai/llms.ts +6 -2
  204. package/src/ai/markdown.ts +2 -1
  205. package/src/ai/mcp/data.ts +6 -0
  206. package/src/ai/openapi-components.ts +9 -3
  207. package/src/ai/site-skill.ts +274 -0
  208. package/src/ai/skills.ts +35 -2
  209. package/src/ai/write-skill.ts +97 -0
  210. package/src/astro/generate.ts +132 -18
  211. package/src/astro/index.ts +1 -0
  212. package/src/astro/integration.ts +35 -0
  213. package/src/astro/module-types.ts +6 -0
  214. package/src/astro/templates.ts +283 -30
  215. package/src/astro/variables.ts +31 -0
  216. package/src/audit/catalog.ts +19 -0
  217. package/src/audit/checks/contrast.ts +183 -0
  218. package/src/audit/checks/i18n.ts +2 -3
  219. package/src/audit/checks/indexability.ts +2 -3
  220. package/src/audit/checks/links.ts +5 -12
  221. package/src/audit/checks/sitemap.ts +2 -3
  222. package/src/audit/redirects.ts +46 -15
  223. package/src/audit/run.ts +2 -0
  224. package/src/audit/types.ts +2 -1
  225. package/src/blume-modules.d.ts +7 -0
  226. package/src/captcha/client.ts +152 -0
  227. package/src/captcha/hcaptcha.ts +36 -0
  228. package/src/captcha/index.ts +28 -0
  229. package/src/captcha/schema.ts +32 -0
  230. package/src/captcha/turnstile.ts +38 -0
  231. package/src/captcha/verify.ts +71 -0
  232. package/src/cli/command-meta.ts +5 -0
  233. package/src/cli/commands/doctor.ts +22 -16
  234. package/src/cli/commands/skill.ts +96 -0
  235. package/src/cli/index.ts +5 -0
  236. package/src/cli/required-secrets.ts +71 -29
  237. package/src/components/BlumePage.astro +2 -0
  238. package/src/components/content/ApiEndpoint.astro +18 -0
  239. package/src/components/content/ApiField.astro +79 -0
  240. package/src/components/content/ApiPlayground.astro +62 -0
  241. package/src/components/content/ApiRail.astro +19 -0
  242. package/src/components/content/Color.astro +1 -0
  243. package/src/components/content/FileTree.astro +1 -0
  244. package/src/components/content/GithubInfo.astro +1 -0
  245. package/src/components/content/Panel.astro +1 -0
  246. package/src/components/content/ParamField.astro +25 -0
  247. package/src/components/content/RequestExample.astro +17 -0
  248. package/src/components/content/ResponseExample.astro +17 -0
  249. package/src/components/content/ResponseField.astro +32 -0
  250. package/src/components/content/Step.astro +1 -0
  251. package/src/components/content/Tile.astro +1 -0
  252. package/src/components/content/Tooltip.astro +1 -0
  253. package/src/components/content/Tree.astro +1 -0
  254. package/src/components/content/TypeTable.astro +4 -1
  255. package/src/components/content/View.astro +21 -0
  256. package/src/components/content/ViewSwitcher.astro +168 -0
  257. package/src/components/content/api-field.ts +100 -0
  258. package/src/components/content/api-page.ts +224 -0
  259. package/src/components/content/view-switcher.ts +71 -0
  260. package/src/components/index.ts +2 -0
  261. package/src/components/islands/Assistant.astro +10 -1
  262. package/src/components/islands/assistant.tsx +104 -14
  263. package/src/components/islands/code-question.ts +62 -0
  264. package/src/components/islands/hooks.ts +110 -21
  265. package/src/components/islands/support-link.ts +68 -0
  266. package/src/components/layout/Analytics.astro +11 -2
  267. package/src/components/layout/Banner.astro +14 -10
  268. package/src/components/layout/Breadcrumbs.astro +6 -2
  269. package/src/components/layout/ConsentBanner.astro +62 -0
  270. package/src/components/layout/ConsentHead.astro +38 -0
  271. package/src/components/layout/Directory.astro +94 -0
  272. package/src/components/layout/DrawerSwitchers.astro +51 -0
  273. package/src/components/layout/Empty.astro +2 -2
  274. package/src/components/layout/Header.astro +122 -80
  275. package/src/components/layout/LanguageSwitcher.astro +48 -15
  276. package/src/components/layout/NarrationPlayer.astro +1085 -0
  277. package/src/components/layout/NavSelector.astro +33 -7
  278. package/src/components/layout/PageFeedback.astro +54 -49
  279. package/src/components/layout/PageLayout.astro +71 -3
  280. package/src/components/layout/ReferenceLayout.astro +17 -6
  281. package/src/components/layout/RelatedPages.astro +42 -0
  282. package/src/components/layout/RootLayout.astro +308 -45
  283. package/src/components/layout/Search.astro +31 -17
  284. package/src/components/layout/SiteFooter.astro +124 -0
  285. package/src/components/layout/SiteMetatags.astro +16 -0
  286. package/src/components/layout/consent/native.ts +79 -0
  287. package/src/components/layout/consent/types.ts +37 -0
  288. package/src/components/layout/footer-links.ts +53 -0
  289. package/src/components/layout/footer-socials.ts +87 -0
  290. package/src/components/layout/locale-redirect.ts +107 -0
  291. package/src/components/layout/nav-utils.ts +83 -0
  292. package/src/components/layout/page-feedback.ts +96 -0
  293. package/src/components/layout/search/analytics.ts +98 -0
  294. package/src/components/layout/search/flexsearch.ts +17 -5
  295. package/src/components/layout/search/orama-cloud.ts +26 -14
  296. package/src/components/layout/search/types.ts +20 -0
  297. package/src/components/layout/search/typesense.ts +5 -1
  298. package/src/components/openapi/Operation.astro +161 -13
  299. package/src/components/openapi/RequestBody.astro +6 -4
  300. package/src/components/openapi/RequestPanel.astro +59 -7
  301. package/src/components/openapi/Responses.astro +6 -4
  302. package/src/components/openapi/async-snippets.ts +4 -4
  303. package/src/components/openapi/code-samples.ts +97 -0
  304. package/src/components/openapi/security.ts +6 -3
  305. package/src/components/openapi/snippets.ts +869 -8
  306. package/src/components/props.ts +6 -0
  307. package/src/consent/client.ts +95 -0
  308. package/src/consent/clients.ts +19 -0
  309. package/src/consent/ethyca.ts +71 -0
  310. package/src/consent/head.ts +24 -0
  311. package/src/consent/index.ts +37 -0
  312. package/src/consent/init.ts +29 -0
  313. package/src/consent/native.ts +36 -0
  314. package/src/consent/osano.ts +59 -0
  315. package/src/consent/schema.ts +30 -0
  316. package/src/core/builtin-tags.ts +5 -0
  317. package/src/core/client-address.ts +19 -0
  318. package/src/core/config-input.ts +194 -20
  319. package/src/core/data.ts +44 -4
  320. package/src/core/diagnostics.ts +3 -2
  321. package/src/core/footer.ts +26 -0
  322. package/src/core/graph.ts +39 -36
  323. package/src/core/i18n-ui.ts +82 -2
  324. package/src/core/includes.ts +20 -3
  325. package/src/core/links.ts +16 -2
  326. package/src/core/localizable.ts +26 -0
  327. package/src/core/navigation.ts +43 -12
  328. package/src/core/page-modes.ts +56 -0
  329. package/src/core/project-graph.ts +111 -5
  330. package/src/core/redirect-patterns.ts +491 -0
  331. package/src/core/related.ts +131 -0
  332. package/src/core/schema.ts +318 -64
  333. package/src/core/sources/normalize.ts +2 -1
  334. package/src/core/sources/read.ts +8 -3
  335. package/src/core/types.ts +1 -1
  336. package/src/core/ui-packs/ar.ts +43 -0
  337. package/src/core/ui-packs/bg.ts +45 -0
  338. package/src/core/ui-packs/bn.ts +43 -0
  339. package/src/core/ui-packs/ca.ts +46 -0
  340. package/src/core/ui-packs/cs.ts +44 -0
  341. package/src/core/ui-packs/da.ts +45 -0
  342. package/src/core/ui-packs/de.ts +46 -0
  343. package/src/core/ui-packs/el.ts +45 -0
  344. package/src/core/ui-packs/es.ts +46 -0
  345. package/src/core/ui-packs/fa.ts +45 -0
  346. package/src/core/ui-packs/fi.ts +45 -0
  347. package/src/core/ui-packs/fr.ts +46 -0
  348. package/src/core/ui-packs/he.ts +43 -0
  349. package/src/core/ui-packs/hi.ts +44 -0
  350. package/src/core/ui-packs/hr.ts +45 -0
  351. package/src/core/ui-packs/hu.ts +44 -0
  352. package/src/core/ui-packs/id.ts +45 -0
  353. package/src/core/ui-packs/it.ts +45 -0
  354. package/src/core/ui-packs/ja.ts +45 -0
  355. package/src/core/ui-packs/ko.ts +44 -0
  356. package/src/core/ui-packs/nl.ts +46 -0
  357. package/src/core/ui-packs/no.ts +44 -0
  358. package/src/core/ui-packs/pl.ts +45 -0
  359. package/src/core/ui-packs/pt-br.ts +46 -0
  360. package/src/core/ui-packs/pt.ts +45 -0
  361. package/src/core/ui-packs/ro.ts +45 -0
  362. package/src/core/ui-packs/ru.ts +45 -0
  363. package/src/core/ui-packs/sk.ts +44 -0
  364. package/src/core/ui-packs/sr.ts +45 -0
  365. package/src/core/ui-packs/sv.ts +44 -0
  366. package/src/core/ui-packs/th.ts +43 -0
  367. package/src/core/ui-packs/tr.ts +45 -0
  368. package/src/core/ui-packs/uk.ts +45 -0
  369. package/src/core/ui-packs/vi.ts +45 -0
  370. package/src/core/ui-packs/zh-tw.ts +43 -0
  371. package/src/core/ui-packs/zh.ts +43 -0
  372. package/src/core/variables.ts +103 -0
  373. package/src/deploy/artifacts.ts +77 -8
  374. package/src/deploy/cloudflare-negotiation.ts +35 -5
  375. package/src/deploy/headers.ts +2 -1
  376. package/src/deploy/node-headers.ts +63 -9
  377. package/src/deploy/platforms/cloudflare.ts +32 -0
  378. package/src/deploy/platforms/netlify.ts +33 -1
  379. package/src/deploy/platforms/vercel.ts +37 -2
  380. package/src/deploy/redirects.ts +91 -24
  381. package/src/deploy/vercel-negotiation.ts +36 -0
  382. package/src/markdown/api-rail.ts +259 -0
  383. package/src/markdown/code-title.ts +35 -9
  384. package/src/markdown/features.ts +3 -2
  385. package/src/markdown/fence-meta.ts +2 -0
  386. package/src/markdown/include.ts +11 -1
  387. package/src/markdown/index.ts +28 -5
  388. package/src/markdown/math.ts +4 -4
  389. package/src/markdown/variables.ts +56 -0
  390. package/src/markdown/views.ts +82 -0
  391. package/src/narration/build.ts +412 -0
  392. package/src/narration/player.ts +249 -0
  393. package/src/narration/provider.ts +29 -0
  394. package/src/narration/script.ts +592 -0
  395. package/src/og/card.ts +7 -6
  396. package/src/openapi/model.ts +57 -24
  397. package/src/openapi/overlay.ts +256 -0
  398. package/src/openapi/parse.ts +55 -2
  399. package/src/openapi/references.ts +21 -5
  400. package/src/openapi/render-mdx.ts +5 -1
  401. package/src/openapi/scalar.ts +40 -6
  402. package/src/openapi/source.ts +1 -1
  403. package/src/ratelimit/cloudflare.ts +54 -0
  404. package/src/ratelimit/index.ts +30 -0
  405. package/src/ratelimit/memory.ts +45 -0
  406. package/src/ratelimit/runtime.ts +229 -0
  407. package/src/ratelimit/schema.ts +28 -0
  408. package/src/ratelimit/upstash.ts +30 -0
  409. package/src/ratelimit/wrangler.ts +70 -0
  410. package/src/reference/asyncapi.ts +2 -2
  411. package/src/reference/graphql.ts +5 -2
  412. package/src/reference/openapi.ts +21 -7
  413. package/src/reference/options.ts +51 -7
  414. package/src/reference/scalar.ts +33 -8
  415. package/src/registry/eject.ts +20 -4
  416. package/src/registry/registry.ts +7 -0
  417. package/src/search/documents.ts +26 -2
  418. package/src/search/orama-index.ts +28 -3
  419. package/src/search/pagefind-ranking.ts +39 -0
  420. package/src/search/sync/algolia.ts +15 -4
  421. package/src/search/sync/orama-cloud.ts +3 -0
  422. package/src/search/sync/typesense.ts +5 -0
  423. package/src/seo/metatags.ts +67 -0
  424. package/src/theme/chrome-icons.ts +1 -0
  425. package/src/theme/color.ts +500 -0
  426. package/src/theme/entry.ts +56 -3
  427. package/src/theme/palette.ts +121 -45
  428. package/src/translate/prompts.ts +1 -0
  429. package/src/translate/validate.ts +8 -2
  430. package/src/upgrade/upgrade.ts +4 -171
  431. package/dist/cli/chunk-364znk6q.js +0 -75
  432. package/dist/cli/chunk-364znk6q.js.map +0 -11
  433. package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
  434. package/dist/cli/chunk-9t7a85s3.js.map +0 -10
  435. package/dist/cli/chunk-c8chx29p.js.map +0 -36
  436. package/dist/cli/chunk-pehfxfta.js.map +0 -10
  437. package/dist/cli/chunk-pv29h0wf.js.map +0 -190
  438. package/dist/cli/chunk-q58y5e6a.js.map +0 -10
  439. package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
  440. package/dist/cli/chunk-yfyb25rh.js.map +0 -14
  441. package/docs/content/sources.mdx +0 -334
  442. /package/dist/cli/{chunk-2eytanqx.js.map → chunk-1n228xqb.js.map} +0 -0
  443. /package/dist/cli/{chunk-35d4wj9f.js.map → chunk-2n4ps1b3.js.map} +0 -0
  444. /package/dist/cli/{chunk-e04dxsz1.js.map → chunk-4ejxbzee.js.map} +0 -0
  445. /package/dist/cli/{chunk-tzmab476.js.map → chunk-5ffywsmb.js.map} +0 -0
  446. /package/dist/cli/{chunk-2z928egk.js.map → chunk-5wj2qwn2.js.map} +0 -0
  447. /package/dist/cli/{chunk-b07cmahc.js.map → chunk-amrb6hgh.js.map} +0 -0
  448. /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-cmtcnh9f.js.map} +0 -0
  449. /package/dist/cli/{chunk-crgn1q09.js.map → chunk-e7vvk5ya.js.map} +0 -0
  450. /package/dist/cli/{chunk-tkacnehg.js.map → chunk-gp84za0h.js.map} +0 -0
  451. /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-p804f3pe.js.map} +0 -0
  452. /package/dist/cli/{chunk-8ktnccpt.js.map → chunk-ta27feev.js.map} +0 -0
  453. /package/dist/cli/{chunk-a58773jm.js.map → chunk-y4ykbark.js.map} +0 -0
  454. /package/dist/cli/{chunk-p3v96n38.js.map → chunk-y5h4r2y0.js.map} +0 -0
  455. /package/dist/cli/{chunk-acanzt5p.js.map → chunk-yj17vs39.js.map} +0 -0
@@ -27,6 +27,8 @@ 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,
@@ -44,6 +46,7 @@ import {
44
46
  } from "../core/content-assets.ts";
45
47
  import type {
46
48
  BlumeBanner,
49
+ BlumeDataConfig,
47
50
  BlumeData,
48
51
  BlumeFavicon,
49
52
  BlumeLogo,
@@ -58,6 +61,7 @@ import {
58
61
  import { EN_UI, resolveUIStrings } from "../core/i18n-ui.ts";
59
62
  import { resolveFallbackLocale } from "../core/i18n.ts";
60
63
  import { buildIncludeGraph } from "../core/includes.ts";
64
+ import { resolveLocalizable } from "../core/localizable.ts";
61
65
  import {
62
66
  validateNavTargets,
63
67
  validateSearchPopularIcons,
@@ -85,6 +89,7 @@ import type { AsyncApiSpecValue } from "../openapi/asyncapi.ts";
85
89
  import type { ApiSpecData, HttpMethod, OpenApiData } from "../openapi/model.ts";
86
90
  import { HTTP_METHODS, withServerDefaults } from "../openapi/model.ts";
87
91
  import {
92
+ apiPagesUseBuiltinProxy,
88
93
  builtinProxyReferences,
89
94
  hasScalarReferences,
90
95
  needsPlaygroundProxy,
@@ -159,6 +164,7 @@ import {
159
164
  runtimeTsconfigTemplate,
160
165
  featuresTemplate,
161
166
  navFragmentTemplate,
167
+ consentClientTemplate,
162
168
  searchClientTemplate,
163
169
  searchEndpointTemplate,
164
170
  stagedContentDir,
@@ -749,12 +755,12 @@ const isStringShorthand = <T>(value: T | string): value is string =>
749
755
  typeof value === "string";
750
756
 
751
757
  /**
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
758
+ * The URL behind the footer's repo mark. A string is used as-is: `github`
759
+ * drives the per-page edit link, the footer mark and the manifest's
754
760
  * `repository` together, so a project whose docs repo is private has to unset
755
761
  * all three, and would otherwise have no way to point the mark at anything.
756
762
  */
757
- const headerRepoUrl = (
763
+ const footerRepoUrl = (
758
764
  repo: boolean | string,
759
765
  derived: string | null
760
766
  ): string | null => {
@@ -961,11 +967,53 @@ const resolveBanner = (config: ResolvedConfig): BlumeBanner | null => {
961
967
  return {
962
968
  content: banner.content,
963
969
  dismissible: banner.dismissible,
964
- key: banner.id ?? banner.content,
970
+ key:
971
+ banner.id ??
972
+ resolveLocalizable(banner.content, undefined, config.i18n?.defaultLocale),
965
973
  link: banner.link,
966
974
  };
967
975
  };
968
976
 
977
+ /** The URL the built-in proxy is injected at (see {@link planPlaygroundProxy}). */
978
+ export const playgroundProxyPattern = (config: ResolvedConfig): string =>
979
+ withBasePath(config.basePath, "/_api-proxy");
980
+
981
+ /**
982
+ * The hand-written endpoint defaults for the runtime, the playground's
983
+ * `proxy: true` resolved to the built-in route's URL, as an OpenAPI
984
+ * reference's is.
985
+ */
986
+ const resolveApiPages = (config: ResolvedConfig): BlumeDataConfig["api"] => {
987
+ const { auth, playground, server } = config.api;
988
+ const resolved: BlumeDataConfig["api"] = {
989
+ playground: {
990
+ enabled: playground.enabled,
991
+ proxy:
992
+ playground.proxy === true
993
+ ? playgroundProxyPattern(config)
994
+ : playground.proxy,
995
+ },
996
+ };
997
+ if (auth) {
998
+ resolved.auth = auth;
999
+ }
1000
+ if (server) {
1001
+ resolved.server = server;
1002
+ }
1003
+ return resolved;
1004
+ };
1005
+
1006
+ /** The footer config for the runtime: `null` when unset or empty, so no bare border renders. */
1007
+ const resolveFooter = (
1008
+ config: ResolvedConfig
1009
+ ): ResolvedConfig["footer"] | null => {
1010
+ const { footer } = config;
1011
+ return footer &&
1012
+ (footer.links.length > 0 || Object.keys(footer.socials).length > 0)
1013
+ ? footer
1014
+ : null;
1015
+ };
1016
+
969
1017
  /**
970
1018
  * The OG card's brand mark: a `seo.og.logo` of `false` opts out of any mark,
971
1019
  * a configured SVG wins over the site logo, and a non-SVG value resolves to
@@ -1036,6 +1084,22 @@ const resolveGithubData = (
1036
1084
  }
1037
1085
  : null;
1038
1086
 
1087
+ /** The assistant's snapshot: what the panel needs, never a secret. */
1088
+ const resolveAssistant = (
1089
+ config: ResolvedConfig
1090
+ ): BlumeDataConfig["assistant"] => {
1091
+ const { assistant } = config.ai;
1092
+ if (!assistant?.enabled) {
1093
+ return null;
1094
+ }
1095
+ return {
1096
+ captcha: assistant.captcha ? captchaSettings(assistant.captcha) : null,
1097
+ endpoint: assistant.endpoint ?? null,
1098
+ suggestions: assistant.suggestions,
1099
+ support: assistant.support ?? null,
1100
+ };
1101
+ };
1102
+
1039
1103
  /** Serialize the content graph into the data module the runtime consumes. */
1040
1104
  export const buildRuntimeData = (project: BlumeProject): string => {
1041
1105
  const { config, context, graph, manifest } = project;
@@ -1067,10 +1131,10 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1067
1131
 
1068
1132
  const { i18n } = config;
1069
1133
 
1070
- // Resolve the header repo link per locale. API references no longer add a tab
1134
+ // Resolve the footer's repo link per locale. API references no longer add a tab
1071
1135
  // automatically — authors point a `navigation.tabs` entry at the reference
1072
1136
  // route to surface it (see `referenceRoutes`).
1073
- const markUrl = headerRepoUrl(config.navigation.repo, repoUrl);
1137
+ const markUrl = footerRepoUrl(config.navigation.repo, repoUrl);
1074
1138
  const withRepoUrl = (nav: Navigation): Navigation => ({
1075
1139
  ...nav,
1076
1140
  repoUrl: markUrl,
@@ -1117,17 +1181,14 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1117
1181
  const data: BlumeData = {
1118
1182
  config: {
1119
1183
  analytics: config.analytics,
1184
+ api: resolveApiPages(config),
1120
1185
  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,
1186
+ assistant: resolveAssistant(config),
1127
1187
  banner: resolveBanner(config),
1128
1188
  basePath: config.basePath,
1129
1189
  codeThemes: config.markdown.code.theme,
1130
1190
  codeWrap: config.markdown.code.wrap,
1191
+ consent: config.consent,
1131
1192
  dateFormat: config.dateFormat,
1132
1193
  description: config.description,
1133
1194
  discovery: {
@@ -1139,7 +1200,9 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1139
1200
  sitemap: config.seo.sitemap && Boolean(config.deployment.options.site),
1140
1201
  },
1141
1202
  favicon: resolveFavicon(project),
1142
- feedback: config.feedback,
1203
+ feedback: config.feedback.enabled,
1204
+ feedbackComments: config.feedback.comments,
1205
+ footer: resolveFooter(config),
1143
1206
  github: resolveGithubData(github),
1144
1207
  i18n: i18n
1145
1208
  ? {
@@ -1153,6 +1216,7 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1153
1216
  dir,
1154
1217
  label,
1155
1218
  })),
1219
+ routeByBrowserLanguage: i18n.routeByBrowserLanguage,
1156
1220
  }
1157
1221
  : null,
1158
1222
  // `undefined` members drop out of the JSON snapshot; the null keeps the
@@ -1172,6 +1236,10 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1172
1236
  route: config.agents.mcp.route,
1173
1237
  }
1174
1238
  : null,
1239
+ metatags: config.seo.metatags ?? null,
1240
+ narration: config.narration.enabled
1241
+ ? { generated: config.narration.provider !== null }
1242
+ : null,
1175
1243
  // `og.enabled` is resolved to a definite boolean in `loadConfig`; coerce
1176
1244
  // the optional schema type so the serialized shape stays `boolean`.
1177
1245
  // Card fonts are baked into the generated OG endpoint (they can carry
@@ -1496,10 +1564,6 @@ const writeApiFiles = async (
1496
1564
  /** The proxy endpoint's file under the Astro `src/` dir (eject writes it too). */
1497
1565
  export const PLAYGROUND_PROXY_ENTRY = join("blume-openapi", "api-proxy.ts");
1498
1566
 
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
1567
  /**
1504
1568
  * Decide whether to generate the playground's built-in CORS proxy endpoint.
1505
1569
  * Only the Blume renderer's playground with `proxy: true` needs it — a proxy
@@ -1592,6 +1656,47 @@ type DocumentPathItem = { servers?: DocumentServer[] } & Partial<
1592
1656
  export const specOrigins = (data: OpenApiData): string[] =>
1593
1657
  [...new Set(Object.values(data).flatMap(specOriginsOf))].toSorted();
1594
1658
 
1659
+ /** The origin of an absolute URL, or `null` for a path or anything unparsable. */
1660
+ const originOf = (url: string): string | null => {
1661
+ try {
1662
+ return new URL(url).origin;
1663
+ } catch {
1664
+ return null;
1665
+ }
1666
+ };
1667
+
1668
+ /**
1669
+ * The origins hand-written endpoint pages send to through the built-in
1670
+ * proxy: the site's `api.server`, and every page whose `api` names a full
1671
+ * URL. Empty unless those pages use the built-in proxy.
1672
+ */
1673
+ export const apiPageOrigins = (project: BlumeProject): string[] => {
1674
+ const { config } = project;
1675
+ if (!apiPagesUseBuiltinProxy(config)) {
1676
+ return [];
1677
+ }
1678
+ const targets = project.graph.pages.map(
1679
+ (page) => parseApiEndpoint(page.meta.api ?? "")?.target ?? ""
1680
+ );
1681
+ return [config.api.server ?? "", ...targets].flatMap((target) => {
1682
+ const origin = originOf(target);
1683
+ return origin ? [origin] : [];
1684
+ });
1685
+ };
1686
+
1687
+ /**
1688
+ * A warning when the hand-written endpoint pages send through the built-in
1689
+ * proxy but name no absolute origin for it to allow, so it would refuse every
1690
+ * request they send.
1691
+ */
1692
+ export const apiPageProxyWarnings = (project: BlumeProject): string[] =>
1693
+ apiPagesUseBuiltinProxy(project.config) &&
1694
+ apiPageOrigins(project).length === 0
1695
+ ? [
1696
+ "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.",
1697
+ ]
1698
+ : [];
1699
+
1595
1700
  /**
1596
1701
  * Build-time diagnostics for playground sends the built-in proxy would refuse.
1597
1702
  * The baked-in allowlist pools every documented origin, but each spec's
@@ -1644,9 +1749,12 @@ const writeAskFiles = async (
1644
1749
  await write(
1645
1750
  join(srcDir, "pages", "api", "ask.ts"),
1646
1751
  askEndpointTemplate(backend, {
1752
+ captcha: assistant.captcha,
1647
1753
  cors: assistant.cors,
1648
1754
  instructions: assistant.instructions,
1755
+ rateLimit: project.config.rateLimit,
1649
1756
  retrieval: assistant.retrieval,
1757
+ tools: assistant.tools ?? backend.toolsByDefault,
1650
1758
  })
1651
1759
  );
1652
1760
  };
@@ -1863,6 +1971,7 @@ export const generateRuntime = async (
1863
1971
  const askPath = join(srcDir, "generated", "Ask.astro");
1864
1972
  const themePath = join(srcDir, "generated", "app.css");
1865
1973
  const searchClientPath = join(srcDir, "generated", "search-client.ts");
1974
+ const consentClientPath = join(srcDir, "generated", "consent-client.ts");
1866
1975
  const featuresPath = join(srcDir, "generated", "features.ts");
1867
1976
  const examplesPath = join(srcDir, "generated", "examples.ts");
1868
1977
  const examplesThemePath = join(srcDir, "generated", "examples.css");
@@ -2000,7 +2109,9 @@ export const generateRuntime = async (
2000
2109
  // Computed once: the endpoint template bakes it in below. A spec that
2001
2110
  // contributes no origin of its own gets a per-spec diagnostic
2002
2111
  // (`proxyAllowlistWarnings`) — the proxy would refuse its every send.
2003
- const proxyOrigins = specOrigins(openApiData);
2112
+ const proxyOrigins = [
2113
+ ...new Set([...specOrigins(openApiData), ...apiPageOrigins(project)]),
2114
+ ].toSorted();
2004
2115
 
2005
2116
  const hasStaged = staged.size > 0;
2006
2117
  // Only emit a project-scanning `docs` collection when a filesystem source
@@ -2022,6 +2133,7 @@ export const generateRuntime = async (
2022
2133
  aliases: resolveTsconfigAliases(context.root),
2023
2134
  askPath,
2024
2135
  config,
2136
+ consentClientPath,
2025
2137
  contentRoot: docsCollection.base,
2026
2138
  contentRoutes,
2027
2139
  context,
@@ -2186,6 +2298,7 @@ export const generateRuntime = async (
2186
2298
  }),
2187
2299
  writeNotFoundPage(write, srcDir, pages, project.graph.pages),
2188
2300
  write(searchClientPath, searchClientTemplate(config)),
2301
+ write(consentClientPath, consentClientTemplate(config.consent)),
2189
2302
  write(featuresPath, featuresTemplate(clientFeatures)),
2190
2303
  ]);
2191
2304
 
@@ -2258,6 +2371,7 @@ export const generateRuntime = async (
2258
2371
  const warnings: string[] = [
2259
2372
  ...(depsLinkWarning ? [depsLinkWarning] : []),
2260
2373
  ...proxyAllowlistWarnings(config, openApiData),
2374
+ ...apiPageProxyWarnings(project),
2261
2375
  ...reactCompilerWarnings(config, needsReact, reactCompilerPath),
2262
2376
  ...mcp.warnings,
2263
2377
  ...islandDiscovery.warnings,
@@ -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,13 @@ export interface BlumeIntegrationOptions {
336
341
  * its already-scanned project instead.
337
342
  */
338
343
  buildArtifactsRoot?: string;
344
+ /**
345
+ * The pattern redirects (`/beta/:slug*`), compiled against base-less
346
+ * request paths (see `core/redirect-patterns.ts`). Astro's own `redirects`
347
+ * carry only the exact ones, since it can't prerender a pattern's pages, so
348
+ * the dev server answers these itself.
349
+ */
350
+ redirects?: CompiledRedirect[];
339
351
  }
340
352
 
341
353
  /**
@@ -397,6 +409,23 @@ const negotiateMarkdown =
397
409
  next();
398
410
  };
399
411
 
412
+ /**
413
+ * Answer a pattern redirect in dev with its configured status, the way the
414
+ * server wrappers do in a build. Request URLs arrive base-less (see
415
+ * {@link negotiateMarkdown}), and the patterns were based to match.
416
+ */
417
+ const answerPatternRedirects =
418
+ (redirects: readonly CompiledRedirect[]) =>
419
+ (req: IncomingMessage, res: ServerResponse, next: () => void): void => {
420
+ const answer = matchCompiledRedirect(redirects, requestPath(req.url ?? ""));
421
+ if (!answer) {
422
+ next();
423
+ return;
424
+ }
425
+ res.writeHead(answer[1], { Location: answer[0] });
426
+ res.end();
427
+ };
428
+
400
429
  /** The `.d.ts` the integration injects for the `blume:*` virtual modules. */
401
430
  const MODULE_TYPES_FILE = "modules.d.ts";
402
431
 
@@ -502,6 +531,12 @@ export const blumeIntegration = (
502
531
  }),
503
532
  route: "",
504
533
  });
534
+ if (options.redirects) {
535
+ server.middlewares.stack.unshift({
536
+ handle: answerPatternRedirects(options.redirects),
537
+ route: "",
538
+ });
539
+ }
505
540
  },
506
541
  },
507
542
  name: "blume",
@@ -75,6 +75,12 @@ 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
85
  export const createSearch: () =>
80
86
  | import("blume/components/layout/search/types.ts").SearchFn