blume 2.0.2 → 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 (601) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +113 -0
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-6k4ftwze.js → chunk-0gz36akr.js} +18 -2
  5. package/dist/cli/{chunk-6k4ftwze.js.map → chunk-0gz36akr.js.map} +3 -3
  6. package/dist/cli/{chunk-zp79m0ts.js → chunk-1n228xqb.js} +2 -2
  7. package/dist/cli/{chunk-ddndchfr.js → chunk-2f3ndkpw.js} +57 -29
  8. package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
  9. package/dist/cli/{chunk-fsmrqk8a.js → chunk-2f7n4qzt.js} +8 -2
  10. package/dist/cli/{chunk-fsmrqk8a.js.map → chunk-2f7n4qzt.js.map} +3 -3
  11. package/dist/cli/{chunk-ppzjqwx2.js → chunk-2n4ps1b3.js} +17 -18
  12. package/dist/cli/{chunk-ppzjqwx2.js.map → chunk-2n4ps1b3.js.map} +3 -3
  13. package/dist/cli/{chunk-5r8g91qn.js → chunk-43zcf4gz.js} +398 -159
  14. package/dist/cli/chunk-43zcf4gz.js.map +36 -0
  15. package/dist/cli/chunk-4ejxbzee.js +39 -0
  16. package/dist/cli/chunk-4ejxbzee.js.map +10 -0
  17. package/dist/cli/{chunk-hr8ne106.js → chunk-4h8z9vv5.js} +296 -77
  18. package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
  19. package/dist/cli/{chunk-k7pj68a8.js → chunk-5cg2rzgf.js} +18 -16
  20. package/dist/cli/{chunk-k7pj68a8.js.map → chunk-5cg2rzgf.js.map} +2 -2
  21. package/dist/cli/{chunk-h2ez8dzb.js → chunk-5ffywsmb.js} +4 -4
  22. package/dist/cli/{chunk-g698a744.js → chunk-5wj2qwn2.js} +5 -5
  23. package/dist/cli/chunk-6bm0xpgd.js +18 -0
  24. package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
  25. package/dist/cli/{chunk-3yce002v.js → chunk-713mngdq.js} +15 -8
  26. package/dist/cli/chunk-713mngdq.js.map +14 -0
  27. package/dist/cli/{chunk-91ws1n6j.js → chunk-9geymqns.js} +17 -15
  28. package/dist/cli/{chunk-91ws1n6j.js.map → chunk-9geymqns.js.map} +2 -2
  29. package/dist/cli/{chunk-6dtt0zfn.js → chunk-9xr4dgee.js} +27 -18
  30. package/dist/cli/chunk-9xr4dgee.js.map +10 -0
  31. package/dist/cli/{chunk-sqw4ekg1.js → chunk-amrb6hgh.js} +2 -2
  32. package/dist/cli/chunk-cm89scdv.js +443 -0
  33. package/dist/cli/chunk-cm89scdv.js.map +11 -0
  34. package/dist/cli/{chunk-wdrt2k2v.js → chunk-cmtcnh9f.js} +90 -26
  35. package/dist/cli/chunk-cmtcnh9f.js.map +10 -0
  36. package/dist/cli/chunk-cy5bm0j0.js +104 -0
  37. package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
  38. package/dist/cli/{chunk-7mbqtmgb.js → chunk-e7vvk5ya.js} +21 -12
  39. package/dist/cli/chunk-e7vvk5ya.js.map +10 -0
  40. package/dist/cli/{chunk-qkb5a8sa.js → chunk-g2z9x01v.js} +6 -98
  41. package/dist/cli/chunk-g2z9x01v.js.map +10 -0
  42. package/dist/cli/{chunk-273ygyr4.js → chunk-ga0pf4aj.js} +7 -7
  43. package/dist/cli/{chunk-273ygyr4.js.map → chunk-ga0pf4aj.js.map} +3 -3
  44. package/dist/cli/{chunk-h7k3nq3v.js → chunk-gp84za0h.js} +2 -2
  45. package/dist/cli/{chunk-hqp2ajnh.js → chunk-h2a48yhd.js} +195 -73
  46. package/dist/cli/chunk-h2a48yhd.js.map +36 -0
  47. package/dist/cli/{chunk-pbg5a4s3.js → chunk-jnwj5kjj.js} +71 -47
  48. package/dist/cli/chunk-jnwj5kjj.js.map +19 -0
  49. package/dist/cli/chunk-kwrg63tm.js +31 -0
  50. package/dist/cli/chunk-kwrg63tm.js.map +10 -0
  51. package/dist/cli/{chunk-8g8ytmgx.js → chunk-nd1821sk.js} +21 -19
  52. package/dist/cli/{chunk-8g8ytmgx.js.map → chunk-nd1821sk.js.map} +2 -2
  53. package/dist/cli/{chunk-w4bxdvsa.js → chunk-ntv4qrt7.js} +17 -15
  54. package/dist/cli/{chunk-w4bxdvsa.js.map → chunk-ntv4qrt7.js.map} +2 -2
  55. package/dist/cli/{chunk-bfwp9vp6.js → chunk-p804f3pe.js} +7 -7
  56. package/dist/cli/{chunk-4e9b9ra6.js → chunk-py62fewh.js} +6 -6
  57. package/dist/cli/{chunk-4e9b9ra6.js.map → chunk-py62fewh.js.map} +1 -1
  58. package/dist/cli/chunk-q3wxxq39.js +126 -0
  59. package/dist/cli/chunk-q3wxxq39.js.map +11 -0
  60. package/dist/cli/{chunk-j85scx15.js → chunk-rekqz4qg.js} +142 -46
  61. package/dist/cli/chunk-rekqz4qg.js.map +10 -0
  62. package/dist/cli/{chunk-00gs3wqs.js → chunk-ta27feev.js} +1 -1
  63. package/dist/cli/{chunk-v6ya5kcb.js → chunk-xkz5xbtv.js} +4031 -1132
  64. package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
  65. package/dist/cli/{chunk-bbnwccaz.js → chunk-y4ykbark.js} +2 -2
  66. package/dist/cli/{chunk-n1yg3tj3.js → chunk-y5h4r2y0.js} +6 -6
  67. package/dist/cli/{chunk-n1yg3tj3.js.map → chunk-y5h4r2y0.js.map} +3 -3
  68. package/dist/cli/{chunk-nfcyttvj.js → chunk-yj17vs39.js} +9 -9
  69. package/dist/cli/{chunk-nfcyttvj.js.map → chunk-yj17vs39.js.map} +1 -1
  70. package/dist/cli/{chunk-7vtckvaw.js → chunk-yxmk4pec.js} +16 -14
  71. package/dist/cli/{chunk-7vtckvaw.js.map → chunk-yxmk4pec.js.map} +2 -2
  72. package/dist/cli/{chunk-gs7r695n.js → chunk-zccbjcj0.js} +22 -8
  73. package/dist/cli/{chunk-gs7r695n.js.map → chunk-zccbjcj0.js.map} +3 -3
  74. package/dist/cli/{chunk-xh43dwgw.js → chunk-zf748avv.js} +415 -225
  75. package/dist/cli/chunk-zf748avv.js.map +37 -0
  76. package/dist/cli/{chunk-d1v5rhy0.js → chunk-zhvd6adm.js} +16 -14
  77. package/dist/cli/{chunk-d1v5rhy0.js.map → chunk-zhvd6adm.js.map} +2 -2
  78. package/dist/cli/index.js +28 -20
  79. package/dist/cli/index.js.map +5 -5
  80. package/dist/types/ai/agent-surface.d.ts +8 -7
  81. package/dist/types/ai/ai-catalog.d.ts +7 -0
  82. package/dist/types/ai/ask-context.d.ts +22 -0
  83. package/dist/types/ai/ask.d.ts +271 -58
  84. package/dist/types/ai/index.d.ts +2 -2
  85. package/dist/types/ai/link-headers.d.ts +8 -1
  86. package/dist/types/ai/openapi-components.d.ts +5 -2
  87. package/dist/types/ai/relative-links.d.ts +9 -7
  88. package/dist/types/ai/site-skill.d.ts +26 -0
  89. package/dist/types/ai/skills.d.ts +20 -1
  90. package/dist/types/ai/tar.d.ts +1 -3
  91. package/dist/types/analytics/index.d.ts +2 -0
  92. package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
  93. package/dist/types/analytics/schema.d.ts +14 -0
  94. package/dist/types/astro/integration.d.ts +11 -2
  95. package/dist/types/captcha/hcaptcha.d.ts +27 -0
  96. package/dist/types/captcha/index.d.ts +28 -0
  97. package/dist/types/captcha/schema.d.ts +29 -0
  98. package/dist/types/captcha/turnstile.d.ts +28 -0
  99. package/dist/types/components/content/api-field.d.ts +59 -0
  100. package/dist/types/components/content/api-page.d.ts +95 -0
  101. package/dist/types/components/layout/nav-utils.d.ts +26 -0
  102. package/dist/types/components/openapi/helpers.d.ts +137 -0
  103. package/dist/types/components/openapi/security.d.ts +85 -0
  104. package/dist/types/consent/ethyca.d.ts +48 -0
  105. package/dist/types/consent/index.d.ts +37 -0
  106. package/dist/types/consent/native.d.ts +28 -0
  107. package/dist/types/consent/osano.d.ts +42 -0
  108. package/dist/types/consent/schema.d.ts +110 -0
  109. package/dist/types/core/base-path.d.ts +21 -7
  110. package/dist/types/core/config-input.d.ts +196 -27
  111. package/dist/types/core/data.d.ts +49 -4
  112. package/dist/types/core/directive-diagnostics.d.ts +12 -0
  113. package/dist/types/core/footer.d.ts +8 -0
  114. package/dist/types/core/heading-markers.d.ts +5 -7
  115. package/dist/types/core/i18n-ui.d.ts +86 -0
  116. package/dist/types/core/i18n.d.ts +2 -0
  117. package/dist/types/core/includes.d.ts +8 -2
  118. package/dist/types/core/last-modified.d.ts +10 -0
  119. package/dist/types/core/localizable.d.ts +7 -0
  120. package/dist/types/core/meta.d.ts +8 -0
  121. package/dist/types/core/page-modes.d.ts +29 -0
  122. package/dist/types/core/redirect-patterns.d.ts +144 -0
  123. package/dist/types/core/related.d.ts +40 -0
  124. package/dist/types/core/schema.d.ts +558 -56
  125. package/dist/types/core/sources/lower.d.ts +29 -16
  126. package/dist/types/core/sources/normalize.d.ts +13 -1
  127. package/dist/types/core/sources/read.d.ts +5 -0
  128. package/dist/types/core/sources/watch.d.ts +12 -5
  129. package/dist/types/core/standard-schema.d.ts +5 -0
  130. package/dist/types/core/types.d.ts +1 -1
  131. package/dist/types/core/variables.d.ts +42 -0
  132. package/dist/types/deploy/artifacts.d.ts +6 -4
  133. package/dist/types/deploy/headers.d.ts +5 -0
  134. package/dist/types/deploy/node-headers.d.ts +13 -2
  135. package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
  136. package/dist/types/deploy/platforms/netlify.d.ts +7 -0
  137. package/dist/types/deploy/platforms/types.d.ts +8 -0
  138. package/dist/types/deploy/platforms/vercel.d.ts +6 -0
  139. package/dist/types/deploy/redirects.d.ts +61 -22
  140. package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
  141. package/dist/types/markdown/code-title.d.ts +17 -0
  142. package/dist/types/markdown/directives.d.ts +62 -0
  143. package/dist/types/markdown/features.d.ts +24 -2
  144. package/dist/types/markdown/mdast.d.ts +63 -0
  145. package/dist/types/narration/build.d.ts +70 -0
  146. package/dist/types/narration/provider.d.ts +26 -0
  147. package/dist/types/narration/script.d.ts +154 -0
  148. package/dist/types/openapi/asyncapi.d.ts +4 -2
  149. package/dist/types/openapi/model.d.ts +12 -6
  150. package/dist/types/openapi/overlay.d.ts +54 -0
  151. package/dist/types/openapi/parse.d.ts +13 -0
  152. package/dist/types/openapi/references.d.ts +14 -4
  153. package/dist/types/ratelimit/cloudflare.d.ts +39 -0
  154. package/dist/types/ratelimit/index.d.ts +27 -0
  155. package/dist/types/ratelimit/memory.d.ts +36 -0
  156. package/dist/types/ratelimit/schema.d.ts +111 -0
  157. package/dist/types/ratelimit/upstash.d.ts +21 -0
  158. package/dist/types/ratelimit/wrangler.d.ts +23 -0
  159. package/dist/types/reference/asyncapi.d.ts +10 -10
  160. package/dist/types/reference/graphql.d.ts +13 -10
  161. package/dist/types/reference/openapi.d.ts +33 -12
  162. package/dist/types/reference/options.d.ts +45 -5
  163. package/dist/types/reference/scalar.d.ts +13 -0
  164. package/dist/types/reference/schema.d.ts +60 -36
  165. package/dist/types/search/documents.d.ts +12 -1
  166. package/dist/types/search/orama-index.d.ts +4 -0
  167. package/dist/types/seo/metatags.d.ts +20 -0
  168. package/docs/02-deployment.mdx +44 -6
  169. package/docs/03-upgrading.mdx +4 -4
  170. package/docs/04-migrating.mdx +1 -1
  171. package/docs/08-faq.mdx +1 -1
  172. package/docs/advanced/changelog.mdx +2 -2
  173. package/docs/advanced/custom-pages.mdx +3 -3
  174. package/docs/advanced/skills.mdx +14 -0
  175. package/docs/cli/audit.mdx +38 -2
  176. package/docs/cli/evals.mdx +3 -3
  177. package/docs/cli/index.mdx +1 -0
  178. package/docs/cli/translate.mdx +3 -3
  179. package/docs/cli/version.mdx +1 -1
  180. package/docs/configuration/analytics.mdx +22 -1
  181. package/docs/configuration/assistant.mdx +188 -36
  182. package/docs/configuration/consent.mdx +100 -0
  183. package/docs/configuration/customization.mdx +6 -4
  184. package/docs/configuration/index.mdx +63 -5
  185. package/docs/configuration/meta.ts +3 -0
  186. package/docs/configuration/narration.mdx +119 -0
  187. package/docs/configuration/rate-limiting.mdx +69 -0
  188. package/docs/configuration/search.mdx +30 -2
  189. package/docs/configuration/theming.mdx +3 -1
  190. package/docs/content/components.mdx +107 -1
  191. package/docs/content/frontmatter.mdx +77 -1
  192. package/docs/content/i18n.mdx +40 -3
  193. package/docs/content/includes.mdx +16 -0
  194. package/docs/content/index.mdx +4 -2
  195. package/docs/content/islands.mdx +1 -1
  196. package/docs/content/meta.mdx +4 -1
  197. package/docs/content/meta.ts +1 -0
  198. package/docs/content/navigation.mdx +28 -6
  199. package/docs/content/sources/contentful.mdx +32 -0
  200. package/docs/content/sources/custom.mdx +39 -0
  201. package/docs/content/sources/github-releases.mdx +31 -0
  202. package/docs/content/sources/index.mdx +91 -0
  203. package/docs/content/sources/meta.ts +16 -0
  204. package/docs/content/sources/notion.mdx +32 -0
  205. package/docs/content/sources/obsidian.mdx +37 -0
  206. package/docs/content/sources/payload.mdx +30 -0
  207. package/docs/content/sources/remote-mdx.mdx +40 -0
  208. package/docs/content/sources/sanity.mdx +29 -0
  209. package/docs/content/sources/strapi.mdx +31 -0
  210. package/docs/content/syntax.mdx +81 -2
  211. package/docs/content/variables.mdx +41 -0
  212. package/docs/content/versioning.mdx +1 -1
  213. package/docs/discoverability/agent-discovery.mdx +30 -3
  214. package/docs/discoverability/index.mdx +3 -2
  215. package/docs/discoverability/llms-txt.mdx +1 -1
  216. package/docs/discoverability/markdown.mdx +2 -2
  217. package/docs/discoverability/metadata.mdx +17 -0
  218. package/docs/discoverability/open-graph.mdx +5 -3
  219. package/docs/discoverability/rss.mdx +1 -1
  220. package/docs/references/api-pages.mdx +74 -0
  221. package/docs/references/asyncapi.mdx +2 -2
  222. package/docs/references/graphql.mdx +3 -3
  223. package/docs/references/meta.ts +1 -1
  224. package/docs/references/openapi.mdx +106 -5
  225. package/docs/references/scalar.mdx +3 -1
  226. package/package.json +36 -1
  227. package/skills/blume/SKILL.md +3 -0
  228. package/skills/blume-migrate/SKILL.md +5 -5
  229. package/skills/blume-migrate/references/docusaurus.md +3 -3
  230. package/skills/blume-migrate/references/fumadocs.md +1 -1
  231. package/skills/blume-migrate/references/mintlify.md +37 -19
  232. package/skills/blume-migrate/references/nextra.md +3 -3
  233. package/skills/blume-migrate/references/starlight.md +2 -1
  234. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +67 -16
  235. package/skills/blume-write-skill/SKILL.md +82 -0
  236. package/src/ai/agent-readability.ts +4 -3
  237. package/src/ai/agent-surface.ts +9 -7
  238. package/src/ai/ai-catalog.ts +12 -5
  239. package/src/ai/api/handlers.ts +2 -2
  240. package/src/ai/api/spec.ts +2 -2
  241. package/src/ai/api-catalog.ts +6 -2
  242. package/src/ai/ask-context.ts +73 -20
  243. package/src/ai/ask-data.ts +6 -0
  244. package/src/ai/ask-tools.ts +142 -0
  245. package/src/ai/ask.ts +354 -76
  246. package/src/ai/changelog-markdown.ts +2 -2
  247. package/src/ai/component-markdown.ts +75 -0
  248. package/src/ai/cors.ts +2 -0
  249. package/src/ai/index.ts +12 -0
  250. package/src/ai/link-headers.ts +14 -5
  251. package/src/ai/llms.ts +24 -9
  252. package/src/ai/markdown.ts +2 -1
  253. package/src/ai/mcp/data.ts +6 -0
  254. package/src/ai/mcp/discovery.ts +2 -2
  255. package/src/ai/mcp/query.ts +2 -2
  256. package/src/ai/mcp/server.ts +2 -2
  257. package/src/ai/openapi-components.ts +31 -9
  258. package/src/ai/relative-links.ts +42 -26
  259. package/src/ai/serializers.ts +2 -1
  260. package/src/ai/site-skill.ts +274 -0
  261. package/src/ai/skills.ts +49 -3
  262. package/src/ai/tar.ts +139 -12
  263. package/src/ai/write-skill.ts +97 -0
  264. package/src/analytics/head.ts +4 -0
  265. package/src/analytics/index.ts +5 -0
  266. package/src/analytics/one-dollar-stats.ts +86 -0
  267. package/src/analytics/schema.ts +2 -0
  268. package/src/astro/generate.ts +133 -19
  269. package/src/astro/include-hmr.ts +31 -12
  270. package/src/astro/include-refresh.ts +19 -8
  271. package/src/astro/index.ts +1 -0
  272. package/src/astro/integration.ts +143 -14
  273. package/src/astro/module-types.ts +6 -0
  274. package/src/astro/runtime-modules.ts +28 -13
  275. package/src/astro/templates.ts +364 -67
  276. package/src/astro/variables.ts +31 -0
  277. package/src/audit/catalog.ts +19 -0
  278. package/src/audit/checks/contrast.ts +183 -0
  279. package/src/audit/checks/i18n.ts +2 -3
  280. package/src/audit/checks/indexability.ts +2 -3
  281. package/src/audit/checks/links.ts +13 -13
  282. package/src/audit/checks/sitemap.ts +2 -3
  283. package/src/audit/graph.ts +3 -1
  284. package/src/audit/redirects.ts +46 -15
  285. package/src/audit/run.ts +14 -9
  286. package/src/audit/snapshot.ts +5 -0
  287. package/src/audit/types.ts +2 -1
  288. package/src/blume-modules.d.ts +7 -0
  289. package/src/captcha/client.ts +152 -0
  290. package/src/captcha/hcaptcha.ts +36 -0
  291. package/src/captcha/index.ts +28 -0
  292. package/src/captcha/schema.ts +32 -0
  293. package/src/captcha/turnstile.ts +38 -0
  294. package/src/captcha/verify.ts +71 -0
  295. package/src/cli/args.ts +32 -0
  296. package/src/cli/command-meta.ts +5 -0
  297. package/src/cli/commands/audit.ts +4 -1
  298. package/src/cli/commands/doctor.ts +25 -17
  299. package/src/cli/commands/eval.ts +19 -11
  300. package/src/cli/commands/skill.ts +96 -0
  301. package/src/cli/commands/translate.ts +9 -12
  302. package/src/cli/commands/validate.ts +3 -1
  303. package/src/cli/dev-lock.ts +157 -37
  304. package/src/cli/index.ts +5 -0
  305. package/src/cli/report-format.ts +11 -6
  306. package/src/cli/required-secrets.ts +71 -29
  307. package/src/components/BlumePage.astro +2 -0
  308. package/src/components/colors.ts +19 -0
  309. package/src/components/content/ApiEndpoint.astro +18 -0
  310. package/src/components/content/ApiField.astro +79 -0
  311. package/src/components/content/ApiPlayground.astro +62 -0
  312. package/src/components/content/ApiRail.astro +19 -0
  313. package/src/components/content/Badge.astro +5 -3
  314. package/src/components/content/Color.astro +1 -0
  315. package/src/components/content/Component.astro +2 -2
  316. package/src/components/content/FileTree.astro +1 -0
  317. package/src/components/content/GithubInfo.astro +1 -0
  318. package/src/components/content/Panel.astro +1 -0
  319. package/src/components/content/ParamField.astro +25 -0
  320. package/src/components/content/RequestExample.astro +17 -0
  321. package/src/components/content/ResponseExample.astro +17 -0
  322. package/src/components/content/ResponseField.astro +32 -0
  323. package/src/components/content/Step.astro +1 -0
  324. package/src/components/content/Tab.astro +0 -1
  325. package/src/components/content/Tabs.astro +4 -0
  326. package/src/components/content/Tile.astro +1 -0
  327. package/src/components/content/Tooltip.astro +1 -0
  328. package/src/components/content/Tree.astro +1 -0
  329. package/src/components/content/TypeTable.astro +4 -1
  330. package/src/components/content/View.astro +21 -0
  331. package/src/components/content/ViewSwitcher.astro +168 -0
  332. package/src/components/content/api-field.ts +100 -0
  333. package/src/components/content/api-page.ts +224 -0
  334. package/src/components/content/badge-color.ts +5 -2
  335. package/src/components/content/base-href.ts +13 -36
  336. package/src/components/content/view-switcher.ts +71 -0
  337. package/src/components/index.ts +2 -0
  338. package/src/components/islands/Assistant.astro +10 -1
  339. package/src/components/islands/assistant.tsx +125 -18
  340. package/src/components/islands/base-path.ts +47 -10
  341. package/src/components/islands/code-question.ts +62 -0
  342. package/src/components/islands/hooks.ts +145 -40
  343. package/src/components/islands/support-link.ts +68 -0
  344. package/src/components/islands/webmcp.ts +4 -2
  345. package/src/components/layout/Analytics.astro +11 -2
  346. package/src/components/layout/Banner.astro +14 -10
  347. package/src/components/layout/Breadcrumbs.astro +11 -4
  348. package/src/components/layout/ConsentBanner.astro +62 -0
  349. package/src/components/layout/ConsentHead.astro +38 -0
  350. package/src/components/layout/Directory.astro +94 -0
  351. package/src/components/layout/DiscoveryLinks.astro +9 -5
  352. package/src/components/layout/DrawerSwitchers.astro +51 -0
  353. package/src/components/layout/Empty.astro +2 -2
  354. package/src/components/layout/Header.astro +124 -82
  355. package/src/components/layout/LanguageSwitcher.astro +50 -17
  356. package/src/components/layout/NarrationPlayer.astro +1085 -0
  357. package/src/components/layout/NavSelector.astro +35 -9
  358. package/src/components/layout/NavTabMenu.astro +3 -3
  359. package/src/components/layout/NavTree.astro +16 -6
  360. package/src/components/layout/PageActions.astro +4 -3
  361. package/src/components/layout/PageFeedback.astro +54 -49
  362. package/src/components/layout/PageLayout.astro +78 -9
  363. package/src/components/layout/Pagination.astro +3 -3
  364. package/src/components/layout/ReferenceLayout.astro +17 -6
  365. package/src/components/layout/RelatedPages.astro +42 -0
  366. package/src/components/layout/RootLayout.astro +313 -50
  367. package/src/components/layout/Search.astro +64 -30
  368. package/src/components/layout/SiteFooter.astro +124 -0
  369. package/src/components/layout/SiteMetatags.astro +16 -0
  370. package/src/components/layout/VersionBanner.astro +2 -2
  371. package/src/components/layout/analytics-client.ts +12 -0
  372. package/src/components/layout/consent/native.ts +79 -0
  373. package/src/components/layout/consent/types.ts +37 -0
  374. package/src/components/layout/footer-links.ts +53 -0
  375. package/src/components/layout/footer-socials.ts +87 -0
  376. package/src/components/layout/locale-redirect.ts +107 -0
  377. package/src/components/layout/nav-utils.ts +83 -0
  378. package/src/components/layout/page-feedback.ts +96 -0
  379. package/src/components/layout/search/analytics.ts +98 -0
  380. package/src/components/layout/search/flexsearch.ts +17 -5
  381. package/src/components/layout/search/orama-cloud.ts +26 -14
  382. package/src/components/layout/search/types.ts +20 -0
  383. package/src/components/layout/search/typesense.ts +5 -1
  384. package/src/components/layout/toc-active.ts +41 -0
  385. package/src/components/layout/toc-element.ts +8 -14
  386. package/src/components/openapi/ApiTagOperations.astro +2 -2
  387. package/src/components/openapi/AsyncApiOperation.astro +7 -4
  388. package/src/components/openapi/GraphqlChip.astro +2 -2
  389. package/src/components/openapi/Operation.astro +163 -13
  390. package/src/components/openapi/Playground.astro +4 -4
  391. package/src/components/openapi/RequestBody.astro +6 -4
  392. package/src/components/openapi/RequestPanel.astro +63 -8
  393. package/src/components/openapi/Responses.astro +6 -4
  394. package/src/components/openapi/SchemaTable.astro +7 -0
  395. package/src/components/openapi/async-snippets.ts +4 -4
  396. package/src/components/openapi/async.ts +38 -6
  397. package/src/components/openapi/code-samples.ts +97 -0
  398. package/src/components/openapi/helpers.ts +19 -9
  399. package/src/components/openapi/message-composer.ts +6 -1
  400. package/src/components/openapi/message.ts +17 -2
  401. package/src/components/openapi/operation-model.ts +81 -11
  402. package/src/components/openapi/panel.ts +4 -2
  403. package/src/components/openapi/param-style.ts +181 -0
  404. package/src/components/openapi/playground-client.ts +73 -16
  405. package/src/components/openapi/request.ts +190 -26
  406. package/src/components/openapi/schema-tree.ts +30 -24
  407. package/src/components/openapi/security.ts +6 -3
  408. package/src/components/openapi/snippets.ts +953 -13
  409. package/src/components/openapi/ws-client.ts +18 -2
  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/base-path.ts +62 -16
  421. package/src/core/builtin-tags.ts +5 -0
  422. package/src/core/client-address.ts +19 -0
  423. package/src/core/config-input.ts +203 -27
  424. package/src/core/data.ts +44 -4
  425. package/src/core/diagnostics.ts +5 -2
  426. package/src/core/directive-diagnostics.ts +99 -0
  427. package/src/core/footer.ts +26 -0
  428. package/src/core/frontmatter.ts +21 -18
  429. package/src/core/graph.ts +39 -36
  430. package/src/core/heading-markers.ts +5 -18
  431. package/src/core/i18n-ui.ts +82 -2
  432. package/src/core/i18n.ts +31 -3
  433. package/src/core/includes.ts +20 -3
  434. package/src/core/last-modified.ts +25 -3
  435. package/src/core/links.ts +16 -2
  436. package/src/core/locale-links.ts +5 -1
  437. package/src/core/localizable.ts +26 -0
  438. package/src/core/meta.ts +33 -19
  439. package/src/core/navigation.ts +71 -20
  440. package/src/core/page-modes.ts +56 -0
  441. package/src/core/project-graph.ts +138 -10
  442. package/src/core/redirect-patterns.ts +491 -0
  443. package/src/core/related.ts +131 -0
  444. package/src/core/schema.ts +342 -68
  445. package/src/core/sources/contentful-rich-text.ts +27 -20
  446. package/src/core/sources/filesystem.ts +20 -2
  447. package/src/core/sources/github-releases.ts +25 -6
  448. package/src/core/sources/lexical.ts +23 -18
  449. package/src/core/sources/lower.ts +201 -34
  450. package/src/core/sources/mdx-remote.ts +51 -16
  451. package/src/core/sources/normalize.ts +327 -91
  452. package/src/core/sources/notion.ts +52 -25
  453. package/src/core/sources/obsidian.ts +23 -6
  454. package/src/core/sources/portable-text.ts +38 -21
  455. package/src/core/sources/read.ts +8 -3
  456. package/src/core/sources/strapi-blocks.ts +20 -16
  457. package/src/core/sources/watch.ts +20 -7
  458. package/src/core/standard-schema.ts +10 -6
  459. package/src/core/types.ts +1 -1
  460. package/src/core/ui-packs/ar.ts +43 -0
  461. package/src/core/ui-packs/bg.ts +45 -0
  462. package/src/core/ui-packs/bn.ts +43 -0
  463. package/src/core/ui-packs/ca.ts +46 -0
  464. package/src/core/ui-packs/cs.ts +44 -0
  465. package/src/core/ui-packs/da.ts +45 -0
  466. package/src/core/ui-packs/de.ts +46 -0
  467. package/src/core/ui-packs/el.ts +45 -0
  468. package/src/core/ui-packs/es.ts +46 -0
  469. package/src/core/ui-packs/fa.ts +45 -0
  470. package/src/core/ui-packs/fi.ts +45 -0
  471. package/src/core/ui-packs/fr.ts +46 -0
  472. package/src/core/ui-packs/he.ts +43 -0
  473. package/src/core/ui-packs/hi.ts +44 -0
  474. package/src/core/ui-packs/hr.ts +45 -0
  475. package/src/core/ui-packs/hu.ts +44 -0
  476. package/src/core/ui-packs/id.ts +45 -0
  477. package/src/core/ui-packs/it.ts +45 -0
  478. package/src/core/ui-packs/ja.ts +45 -0
  479. package/src/core/ui-packs/ko.ts +44 -0
  480. package/src/core/ui-packs/nl.ts +46 -0
  481. package/src/core/ui-packs/no.ts +44 -0
  482. package/src/core/ui-packs/pl.ts +45 -0
  483. package/src/core/ui-packs/pt-br.ts +46 -0
  484. package/src/core/ui-packs/pt.ts +45 -0
  485. package/src/core/ui-packs/ro.ts +45 -0
  486. package/src/core/ui-packs/ru.ts +45 -0
  487. package/src/core/ui-packs/sk.ts +44 -0
  488. package/src/core/ui-packs/sr.ts +45 -0
  489. package/src/core/ui-packs/sv.ts +44 -0
  490. package/src/core/ui-packs/th.ts +43 -0
  491. package/src/core/ui-packs/tr.ts +45 -0
  492. package/src/core/ui-packs/uk.ts +45 -0
  493. package/src/core/ui-packs/vi.ts +45 -0
  494. package/src/core/ui-packs/zh-tw.ts +43 -0
  495. package/src/core/ui-packs/zh.ts +43 -0
  496. package/src/core/variables.ts +103 -0
  497. package/src/core/version-cut.ts +52 -15
  498. package/src/deploy/artifacts.ts +104 -14
  499. package/src/deploy/cloudflare-negotiation.ts +39 -17
  500. package/src/deploy/headers.ts +10 -5
  501. package/src/deploy/node-headers.ts +64 -10
  502. package/src/deploy/platforms/cloudflare.ts +44 -3
  503. package/src/deploy/platforms/netlify.ts +34 -1
  504. package/src/deploy/platforms/node.ts +1 -0
  505. package/src/deploy/platforms/static.ts +1 -0
  506. package/src/deploy/platforms/types.ts +8 -0
  507. package/src/deploy/platforms/vercel.ts +38 -2
  508. package/src/deploy/redirects.ts +139 -36
  509. package/src/deploy/robots.ts +2 -2
  510. package/src/deploy/rss.ts +4 -3
  511. package/src/deploy/sitemap.ts +7 -5
  512. package/src/deploy/vercel-negotiation.ts +36 -0
  513. package/src/markdown/api-rail.ts +259 -0
  514. package/src/markdown/base-links.ts +34 -36
  515. package/src/markdown/code-title.ts +35 -9
  516. package/src/markdown/directives.ts +242 -36
  517. package/src/markdown/features.ts +20 -2
  518. package/src/markdown/fence-meta.ts +2 -0
  519. package/src/markdown/include.ts +11 -1
  520. package/src/markdown/index.ts +35 -11
  521. package/src/markdown/math.ts +4 -4
  522. package/src/markdown/mdast.ts +5 -2
  523. package/src/markdown/relative-links.ts +12 -4
  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 +136 -11
  531. package/src/og/derive.ts +41 -31
  532. package/src/og/index.ts +1 -0
  533. package/src/openapi/asyncapi.ts +4 -2
  534. package/src/openapi/model.ts +77 -36
  535. package/src/openapi/overlay.ts +256 -0
  536. package/src/openapi/parse.ts +55 -2
  537. package/src/openapi/proxy.ts +63 -10
  538. package/src/openapi/references.ts +21 -5
  539. package/src/openapi/render-mdx.ts +46 -3
  540. package/src/openapi/scalar.ts +40 -6
  541. package/src/openapi/source.ts +1 -1
  542. package/src/ratelimit/cloudflare.ts +54 -0
  543. package/src/ratelimit/index.ts +30 -0
  544. package/src/ratelimit/memory.ts +45 -0
  545. package/src/ratelimit/runtime.ts +229 -0
  546. package/src/ratelimit/schema.ts +28 -0
  547. package/src/ratelimit/upstash.ts +30 -0
  548. package/src/ratelimit/wrangler.ts +70 -0
  549. package/src/reference/asyncapi.ts +2 -2
  550. package/src/reference/graphql.ts +5 -2
  551. package/src/reference/openapi.ts +21 -7
  552. package/src/reference/options.ts +51 -7
  553. package/src/reference/scalar.ts +33 -8
  554. package/src/registry/eject.ts +201 -28
  555. package/src/registry/registry.ts +7 -0
  556. package/src/search/adapters/version-scope.ts +30 -0
  557. package/src/search/documents.ts +93 -28
  558. package/src/search/orama-index.ts +28 -3
  559. package/src/search/pagefind-ranking.ts +39 -0
  560. package/src/search/popular.ts +2 -1
  561. package/src/search/sync/algolia.ts +15 -4
  562. package/src/search/sync/orama-cloud.ts +3 -0
  563. package/src/search/sync/typesense.ts +5 -0
  564. package/src/seo/jsonld.ts +7 -3
  565. package/src/seo/metatags.ts +67 -0
  566. package/src/theme/chrome-icons.ts +1 -0
  567. package/src/theme/color.ts +500 -0
  568. package/src/theme/entry.ts +56 -3
  569. package/src/theme/palette.ts +121 -45
  570. package/src/translate/meta.ts +68 -24
  571. package/src/translate/prompts.ts +1 -0
  572. package/src/translate/run.ts +3 -3
  573. package/src/translate/validate.ts +12 -3
  574. package/src/translate/work-list.ts +56 -17
  575. package/src/upgrade/upgrade.ts +4 -171
  576. package/dist/cli/chunk-3yce002v.js.map +0 -14
  577. package/dist/cli/chunk-5r8g91qn.js.map +0 -34
  578. package/dist/cli/chunk-6dtt0zfn.js.map +0 -10
  579. package/dist/cli/chunk-7mbqtmgb.js.map +0 -10
  580. package/dist/cli/chunk-ddndchfr.js.map +0 -14
  581. package/dist/cli/chunk-esh98wmb.js +0 -23
  582. package/dist/cli/chunk-esh98wmb.js.map +0 -10
  583. package/dist/cli/chunk-hqp2ajnh.js.map +0 -35
  584. package/dist/cli/chunk-hr8ne106.js.map +0 -13
  585. package/dist/cli/chunk-j85scx15.js.map +0 -10
  586. package/dist/cli/chunk-mqc662a6.js +0 -75
  587. package/dist/cli/chunk-mqc662a6.js.map +0 -11
  588. package/dist/cli/chunk-pbg5a4s3.js.map +0 -19
  589. package/dist/cli/chunk-qkb5a8sa.js.map +0 -10
  590. package/dist/cli/chunk-v6ya5kcb.js.map +0 -189
  591. package/dist/cli/chunk-wdrt2k2v.js.map +0 -10
  592. package/dist/cli/chunk-xh43dwgw.js.map +0 -36
  593. package/docs/content/sources.mdx +0 -338
  594. /package/dist/cli/{chunk-zp79m0ts.js.map → chunk-1n228xqb.js.map} +0 -0
  595. /package/dist/cli/{chunk-h2ez8dzb.js.map → chunk-5ffywsmb.js.map} +0 -0
  596. /package/dist/cli/{chunk-g698a744.js.map → chunk-5wj2qwn2.js.map} +0 -0
  597. /package/dist/cli/{chunk-sqw4ekg1.js.map → chunk-amrb6hgh.js.map} +0 -0
  598. /package/dist/cli/{chunk-h7k3nq3v.js.map → chunk-gp84za0h.js.map} +0 -0
  599. /package/dist/cli/{chunk-bfwp9vp6.js.map → chunk-p804f3pe.js.map} +0 -0
  600. /package/dist/cli/{chunk-00gs3wqs.js.map → chunk-ta27feev.js.map} +0 -0
  601. /package/dist/cli/{chunk-bbnwccaz.js.map → chunk-y4ykbark.js.map} +0 -0
@@ -2,7 +2,13 @@ import { z } from "zod";
2
2
 
3
3
  import type { AdapterDescriptor, JsonValue } from "../core/adapter.ts";
4
4
  import { adapterDescriptorSchema } from "../core/adapter.ts";
5
- import { hasSources, missingSourcesIssue } from "./options.ts";
5
+ import {
6
+ hasSources,
7
+ missingSourcesIssue,
8
+ overlaysHaveSpec,
9
+ overlaysNeedSpecIssue,
10
+ overlaysSchema,
11
+ } from "./options.ts";
6
12
 
7
13
  /**
8
14
  * What the generated Scalar page imports. Declared on every `scalar()`
@@ -22,6 +28,11 @@ export const scalarSourceSchema = z.strictObject({
22
28
  label: z.string().optional(),
23
29
  /** Emit noindex metadata and omit the page from the sitemap. */
24
30
  noindex: z.boolean().default(false),
31
+ /**
32
+ * OpenAPI Overlay documents applied in order to the document before it's
33
+ * embedded (inlined, so a remote spec with overlays is fetched at build).
34
+ */
35
+ overlays: overlaysSchema,
25
36
  /** Per-source route; defaults to the adapter's `route` (or a derived path). */
26
37
  route: z.string().optional(),
27
38
  /** Local path or `http(s)` URL to the OpenAPI or AsyncAPI document. */
@@ -34,6 +45,8 @@ export interface ScalarSourceOptions {
34
45
  label?: string;
35
46
  /** Emit noindex metadata and omit the page from the sitemap. Defaults to `false`. */
36
47
  noindex?: boolean;
48
+ /** OpenAPI Overlay documents applied in order to the document before it's embedded. */
49
+ overlays?: string[];
37
50
  /** Per-source route; defaults to the adapter's `route` (or a derived path). */
38
51
  route?: string;
39
52
  /** Local path or `http(s)` URL to the OpenAPI or AsyncAPI document. */
@@ -55,6 +68,8 @@ export type ResolvedScalarOptions = {
55
68
 
56
69
  /** The options {@link scalar} maps itself. */
57
70
  export interface ScalarNamedOptions {
71
+ /** OpenAPI Overlay documents for `spec`; with `sources`, each takes its own. */
72
+ overlays?: string[];
58
73
  /** Where the reference mounts. Defaults to `/reference`. */
59
74
  route?: string;
60
75
  /** One or more documents; each renders on its own route by default. */
@@ -87,6 +102,8 @@ export type ScalarOptions = ScalarNamedOptions & {
87
102
  */
88
103
  export const scalarOptionsSchema = z
89
104
  .object({
105
+ /** Overlays for the `spec` shorthand. */
106
+ overlays: z.array(z.string()).optional(),
90
107
  /** Where the reference mounts. */
91
108
  route: z.string().default("/reference"),
92
109
  /** One or more documents; each renders on its own route by default. */
@@ -97,13 +114,21 @@ export const scalarOptionsSchema = z
97
114
  theme: z.string().optional(),
98
115
  })
99
116
  .catchall(z.json())
100
- .transform(({ spec, sources, ...options }): ResolvedScalarOptions => ({
101
- ...options,
102
- sources:
103
- spec === undefined
104
- ? sources
105
- : [scalarSourceSchema.parse({ spec }), ...sources],
106
- }))
117
+ .refine(overlaysHaveSpec, overlaysNeedSpecIssue)
118
+ .transform(
119
+ ({ overlays, spec, sources, ...options }): ResolvedScalarOptions => ({
120
+ ...options,
121
+ sources:
122
+ spec === undefined
123
+ ? sources
124
+ : [
125
+ scalarSourceSchema.parse(
126
+ overlays ? { overlays, spec } : { spec }
127
+ ),
128
+ ...sources,
129
+ ],
130
+ })
131
+ )
107
132
  .refine(hasSources, missingSourcesIssue("scalar"));
108
133
 
109
134
  export type ScalarAdapter = AdapterDescriptor<"scalar", ScalarOptions>;
@@ -3,10 +3,13 @@ import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
3
 
4
4
  import { join, relative } from "pathe";
5
5
 
6
+ import { OPENAPI_PATH } from "../ai/api/paths.ts";
7
+ import { buildApiSpec } from "../ai/api/spec.ts";
6
8
  import { buildAskData } from "../ai/ask-data.ts";
7
9
  import { resolveAskBackend } from "../ai/ask.ts";
8
10
  import { buildRawMarkdown } from "../ai/markdown.ts";
9
11
  import { buildMcpData } from "../ai/mcp/data.ts";
12
+ import type { McpData } from "../ai/mcp/data.ts";
10
13
  import { buildMcpDiscovery, buildMcpServerCard } from "../ai/mcp/discovery.ts";
11
14
  import { planComponentSlots } from "../astro/component-slots.ts";
12
15
  import {
@@ -31,6 +34,11 @@ import {
31
34
  import { discoverIslands } from "../astro/islands.ts";
32
35
  import { customOgRoutes, discoverPages, routeIsTaken } from "../astro/pages.ts";
33
36
  import {
37
+ apiNavigationTemplate,
38
+ apiNotFoundTemplate,
39
+ apiPagesIndexTemplate,
40
+ apiPageTemplate,
41
+ apiSearchTemplate,
34
42
  askComponentTemplate,
35
43
  askEndpointTemplate,
36
44
  astroConfigTemplate,
@@ -46,6 +54,8 @@ import {
46
54
  mcpEndpointTemplate,
47
55
  mcpPageFile,
48
56
  mixedbreadSearchEndpointTemplate,
57
+ notFoundJsonTemplate,
58
+ notFoundMarkdownTemplate,
49
59
  notFoundPageTemplate,
50
60
  ogEndpointTemplate,
51
61
  playgroundProxyTemplate,
@@ -53,6 +63,7 @@ import {
53
63
  rssEndpointTemplate,
54
64
  runtimeDependencies,
55
65
  runtimeTsconfigTemplate,
66
+ consentClientTemplate,
56
67
  searchClientTemplate,
57
68
  searchEndpointTemplate,
58
69
  staticJsonEndpointTemplate,
@@ -68,6 +79,7 @@ import {
68
79
  } from "../core/sources/collection.ts";
69
80
  import type { ProjectContext } from "../core/types.ts";
70
81
  import { buildRssFeeds, renderRssFeed } from "../deploy/rss.ts";
82
+ import { resolveOgFonts } from "../og/derive.ts";
71
83
  import type { OpenApiData } from "../openapi/model.ts";
72
84
  import {
73
85
  hasScalarReferences,
@@ -80,6 +92,7 @@ import {
80
92
  examplesEntryTemplate,
81
93
  tailwindEntryTemplate,
82
94
  } from "../theme/entry.ts";
95
+ import { fontLocaleCodes } from "../theme/fonts.ts";
83
96
  import { buildThemeCss } from "../theme/palette.ts";
84
97
  import { rebaseSourceDirectives } from "../theme/sources.ts";
85
98
  import { twoslashCss } from "../theme/twoslash.ts";
@@ -150,9 +163,12 @@ const askFiles = async (
150
163
  const files = [
151
164
  {
152
165
  content: askEndpointTemplate(backend, {
166
+ captcha: assistant.captcha,
153
167
  cors: assistant.cors,
154
168
  instructions: assistant.instructions,
169
+ rateLimit: project.config.rateLimit,
155
170
  retrieval: assistant.retrieval,
171
+ tools: assistant.tools ?? backend.toolsByDefault,
156
172
  }),
157
173
  path: join(srcDir, "pages", "api", "ask.ts"),
158
174
  },
@@ -231,28 +247,43 @@ const playgroundProxyFiles = (
231
247
  needsPlaygroundProxy(config)
232
248
  ? [
233
249
  {
234
- content: playgroundProxyTemplate(specOrigins(openApiData)),
250
+ content: playgroundProxyTemplate(
251
+ specOrigins(openApiData),
252
+ config.rateLimit
253
+ ),
235
254
  path: join(srcDir, PLAYGROUND_PROXY_ENTRY),
236
255
  },
237
256
  ]
238
257
  : [];
239
258
 
240
259
  /**
241
- * The MCP data snapshot, server endpoint, and `.well-known` discovery
242
- * documents, mirroring `writeMcpFiles` in generate.ts. Empty when the server
243
- * is disabled or its route is already owned by a page.
260
+ * The agent data snapshot (`blume:mcp-data`) behind the MCP server and the
261
+ * JSON docs API, mirroring `publishAgentData` in generate.ts: built when
262
+ * either is on, null when neither needs it.
263
+ */
264
+ const ejectAgentData = async (
265
+ project: BlumeProject,
266
+ userPages: { pattern: string }[]
267
+ ): Promise<McpData | null> =>
268
+ hostsMcp(project, userPages) || project.config.agents.api
269
+ ? await buildMcpData(project)
270
+ : null;
271
+
272
+ /**
273
+ * The MCP server endpoint and `.well-known` discovery documents, mirroring
274
+ * `writeMcpFiles` in generate.ts. Empty when the server is disabled or its
275
+ * route is already owned by a page.
244
276
  */
245
- const mcpFiles = async (
277
+ const mcpFiles = (
246
278
  project: BlumeProject,
247
279
  userPages: { pattern: string }[],
248
280
  srcDir: string,
249
- genDir: string
250
- ): Promise<{ content: string; path: string }[]> => {
251
- if (!hostsMcp(project, userPages)) {
281
+ data: McpData | null
282
+ ): { content: string; path: string }[] => {
283
+ if (!(data && hostsMcp(project, userPages))) {
252
284
  return [];
253
285
  }
254
286
  const { route } = project.config.agents.mcp;
255
- const data = await buildMcpData(project);
256
287
  const discoveryInput = {
257
288
  base: data.base,
258
289
  name: data.name,
@@ -261,10 +292,6 @@ const mcpFiles = async (
261
292
  version: data.version,
262
293
  };
263
294
  return [
264
- {
265
- content: `${JSON.stringify(data)}\n`,
266
- path: join(genDir, "mcp-data.json"),
267
- },
268
295
  {
269
296
  content: mcpEndpointTemplate(),
270
297
  path: join(srcDir, "pages", mcpPageFile(route)),
@@ -280,6 +307,87 @@ const mcpFiles = async (
280
307
  ];
281
308
  };
282
309
 
310
+ /**
311
+ * The JSON docs API, mirroring `planApi` and `writeApiFiles` in generate.ts:
312
+ * the prerendered page index, per-page documents, and navigation; on server
313
+ * output the search endpoint and, unless a user page or a content page already
314
+ * lives under `/api/`, the JSON 404 catch-all; and `/openapi.json`, unless a
315
+ * `public/openapi.json` or a page owns that route. The ejected `llms.txt`,
316
+ * homepage `Link` header, and 404 page advertise these routes, so the ejected
317
+ * app serves them. Empty when `agents.api` is off.
318
+ */
319
+ const apiFiles = (
320
+ project: BlumeProject,
321
+ userPages: { pattern: string }[],
322
+ root: string,
323
+ srcDir: string,
324
+ data: McpData | null
325
+ ): { content: string; path: string }[] => {
326
+ const { config } = project;
327
+ if (!(data && config.agents.api)) {
328
+ return [];
329
+ }
330
+ const server = config.deployment.options.output === "server";
331
+ const apiDir = join(srcDir, "pages", "api");
332
+ const files = [
333
+ {
334
+ content: apiPagesIndexTemplate(),
335
+ path: join(apiDir, "docs", "pages.json.ts"),
336
+ },
337
+ {
338
+ content: apiPageTemplate(),
339
+ path: join(apiDir, "docs", "pages", "[...route].json.ts"),
340
+ },
341
+ {
342
+ content: apiNavigationTemplate(),
343
+ path: join(apiDir, "docs", "navigation.json.ts"),
344
+ },
345
+ ];
346
+ if (server) {
347
+ files.push({
348
+ content: apiSearchTemplate(),
349
+ path: join(apiDir, "docs", "search.ts"),
350
+ });
351
+ }
352
+ const apiOwned =
353
+ userPages.some((page) => page.pattern.startsWith("/api/[")) ||
354
+ project.graph.pages.some(
355
+ (page) => page.route === "/api" || page.route.startsWith("/api/")
356
+ );
357
+ if (server && !apiOwned) {
358
+ files.push({
359
+ content: apiNotFoundTemplate({ base: data.base, site: data.site }),
360
+ path: join(apiDir, "[...path].ts"),
361
+ });
362
+ }
363
+ if (
364
+ !(
365
+ routeIsTaken(userPages, project.graph.pages, OPENAPI_PATH) ||
366
+ existsSync(join(root, "public", "openapi.json"))
367
+ )
368
+ ) {
369
+ files.push({
370
+ content: staticJsonEndpointTemplate(
371
+ buildApiSpec({
372
+ agentReadability: config.agents.agentReadability,
373
+ base: data.base,
374
+ description: config.description,
375
+ llmsTxt: config.agents.llmsTxt.enabled,
376
+ mcpRoute: hostsMcp(project, userPages)
377
+ ? config.agents.mcp.route
378
+ : null,
379
+ name: config.title,
380
+ search: server,
381
+ site: data.site,
382
+ version: data.version,
383
+ })
384
+ ),
385
+ path: join(srcDir, "pages", "openapi.json.ts"),
386
+ });
387
+ }
388
+ return files;
389
+ };
390
+
283
391
  /**
284
392
  * The `/changelog` index page, mirroring `shouldGenerateChangelog` in
285
393
  * generate.ts: emitted when `type: changelog` entries or a release-backed
@@ -346,6 +454,25 @@ const contentAssetFiles = async (
346
454
  ];
347
455
  };
348
456
 
457
+ /**
458
+ * The partial → including-pages map with every path relative to the project
459
+ * root, like every other path in the ejected app, so it holds in any checkout.
460
+ * Its readers (`includeHmrPlugin`, `withIncludeRefresh`) resolve each path
461
+ * against the app's root, which after eject is the project itself.
462
+ */
463
+ const portableIncludeGraph = (
464
+ project: BlumeProject,
465
+ root: string
466
+ ): Record<string, string[]> =>
467
+ Object.fromEntries(
468
+ Object.entries(buildIncludeGraph(project.graph.pages)).map(
469
+ ([partial, includers]) => [
470
+ toPosix(relative(root, partial)),
471
+ includers.map((page) => toPosix(relative(root, page))),
472
+ ]
473
+ )
474
+ );
475
+
349
476
  /** Contents of the configured `examples.css`, or `""` when unset/absent. */
350
477
  /**
351
478
  * Read a user stylesheet that eject inlines into a generated entry under
@@ -547,6 +674,7 @@ export const eject = async (
547
674
  content: astroConfigTemplate({
548
675
  askPath: "./src/generated/Ask.astro",
549
676
  config,
677
+ consentClientPath: "./src/generated/consent-client.ts",
550
678
  contentRoot: relContext.contentRoot,
551
679
  contentRoutes: project.manifest.routes.map((route) => route.path),
552
680
  context: relContext,
@@ -655,7 +783,7 @@ export const eject = async (
655
783
  // hot update's read would silently no-op and partial edits would serve
656
784
  // stale pages. A snapshot like the rest of `src/generated`: the ejected
657
785
  // app owns (and may regenerate or prune) it.
658
- content: `${JSON.stringify(buildIncludeGraph(project.graph.pages))}\n`,
786
+ content: `${JSON.stringify(portableIncludeGraph(project, root))}\n`,
659
787
  path: join(genDir, "includes.json"),
660
788
  },
661
789
  {
@@ -684,36 +812,74 @@ export const eject = async (
684
812
  });
685
813
 
686
814
  if (config.seo.og.enabled) {
815
+ // The default script fallbacks ride along (Google family names, nothing
816
+ // machine-specific), so a non-Latin card still renders after eject. An
817
+ // explicit seo.og.fonts replaces them, and isn't carried over.
818
+ const { fallbacks, families } = resolveOgFonts(
819
+ {
820
+ locales: fontLocaleCodes(config.i18n),
821
+ ogFonts: config.seo.og.fonts,
822
+ themeFonts: config.theme.fonts,
823
+ themeFontsConfigured: false,
824
+ },
825
+ root
826
+ );
687
827
  files.push({
688
828
  content: ogEndpointTemplate(
689
829
  customOgRoutes(pages, config.title, config.seo.og.titles),
690
- { pageDescriptions: config.seo.og.description !== false },
830
+ {
831
+ fallbacks,
832
+ families,
833
+ pageDescriptions: config.seo.og.description !== false,
834
+ },
691
835
  changelog.length > 0
692
836
  ),
693
837
  path: join(srcDir, "pages", "og", "[...slug].png.ts"),
694
838
  });
695
839
  }
696
840
 
697
- // The hosted MCP server and the playground's built-in proxy, mirrored from
698
- // the generated runtime (`[]` when each is off).
841
+ // The hosted MCP server, the JSON docs API, and the playground's built-in
842
+ // proxy, mirrored from the generated runtime (`[]` when each is off). The
843
+ // server and the API share one agent data snapshot.
844
+ const agentData = await ejectAgentData(project, pages);
845
+ if (agentData) {
846
+ files.push({
847
+ content: `${JSON.stringify(agentData)}\n`,
848
+ path: join(genDir, "mcp-data.json"),
849
+ });
850
+ }
699
851
  files.push(
700
- ...(await mcpFiles(project, pages, srcDir, genDir)),
852
+ ...mcpFiles(project, pages, srcDir, agentData),
853
+ ...apiFiles(project, pages, root, srcDir, agentData),
701
854
  ...changelog,
702
855
  ...playgroundProxyFiles(config, openApiData, srcDir)
703
856
  );
704
857
 
705
- // Default 404 page, unless the project already owns `/404` (a custom
706
- // `pages/404.astro` or a `404.md` content page). The ejected project owns the
707
- // file afterwards and can edit or remove it.
858
+ // Default 404 page and its Markdown (`/404.md`) and JSON (`/404.json`)
859
+ // twins, mirroring `writeNotFoundPage` in generate.ts: all three are skipped
860
+ // when the project already owns `/404` (a custom `pages/404.astro` or a
861
+ // `404.md` content page). The ejected project owns the files afterwards and
862
+ // can edit or remove them.
708
863
  if (!routeIsTaken(pages, project.graph.pages, "/404")) {
709
- files.push({
710
- content: notFoundPageTemplate(),
711
- path: join(srcDir, "pages", "404.astro"),
712
- });
864
+ files.push(
865
+ {
866
+ content: notFoundPageTemplate(),
867
+ path: join(srcDir, "pages", "404.astro"),
868
+ },
869
+ {
870
+ content: notFoundMarkdownTemplate(),
871
+ path: join(srcDir, "pages", "404.md.ts"),
872
+ },
873
+ {
874
+ content: notFoundJsonTemplate(),
875
+ path: join(srcDir, "pages", "404.json.ts"),
876
+ }
877
+ );
713
878
  }
714
879
 
715
- // The client-feature loaders behind the `blume:features` alias, and the
716
- // provider-specific client loader behind `blume:search-client`.
880
+ // The client-feature loaders behind the `blume:features` alias, the
881
+ // provider-specific client loader behind `blume:search-client`, and the
882
+ // consent adapter's browser module behind `blume:consent-client`.
717
883
  files.push(
718
884
  {
719
885
  content: featuresTemplate(features),
@@ -722,6 +888,10 @@ export const eject = async (
722
888
  {
723
889
  content: searchClientTemplate(config),
724
890
  path: join(genDir, "search-client.ts"),
891
+ },
892
+ {
893
+ content: consentClientTemplate(config.consent),
894
+ path: join(genDir, "consent-client.ts"),
725
895
  }
726
896
  );
727
897
 
@@ -742,7 +912,10 @@ export const eject = async (
742
912
 
743
913
  if (searchAdapter.kind === "mixedbread") {
744
914
  files.push({
745
- content: mixedbreadSearchEndpointTemplate(searchAdapter.options),
915
+ content: mixedbreadSearchEndpointTemplate(
916
+ searchAdapter.options,
917
+ config.rateLimit
918
+ ),
746
919
  path: join(srcDir, "pages", "api", "search.ts"),
747
920
  });
748
921
  }
@@ -262,6 +262,13 @@ export const registry: RegistryItem[] = [
262
262
  name: "feedback",
263
263
  slot: "Feedback",
264
264
  }),
265
+ layoutComponent({
266
+ description:
267
+ "The site footer: a row of links, social icons, the theme toggle, and the Cookie settings link.",
268
+ file: "SiteFooter.astro",
269
+ name: "footer",
270
+ slot: "Footer",
271
+ }),
265
272
  ...CONTENT_COMPONENTS.map(contentComponent),
266
273
  ];
267
274
 
@@ -0,0 +1,30 @@
1
+ import type { SearchAdapterKind } from "./registry.ts";
2
+
3
+ /**
4
+ * Whether each adapter's client can filter results to one docs version. The
5
+ * source-built indexes (Orama, FlexSearch) store every document's `version`,
6
+ * and the Algolia and Typesense syncs upload it as a facet their clients
7
+ * filter on. Pagefind indexes the built HTML with no version metadata, the
8
+ * Orama Cloud sync uploads no `version`, and the Mixedbread endpoint takes no
9
+ * filter, so those always search every version. Keyed by every kind so a new
10
+ * adapter has to decide.
11
+ */
12
+ const SCOPES_VERSIONS = {
13
+ algolia: true,
14
+ flexsearch: true,
15
+ mixedbread: false,
16
+ none: false,
17
+ orama: true,
18
+ "orama-cloud": false,
19
+ pagefind: false,
20
+ typesense: true,
21
+ } satisfies Record<SearchAdapterKind, boolean>;
22
+
23
+ /**
24
+ * Whether the configured search adapter scopes results to the viewed docs
25
+ * version. The search dialog offers its "All versions" toggle only when it
26
+ * does: on the others the toggle would change nothing, and every query
27
+ * already spans all versions.
28
+ */
29
+ export const scopesVersions = (kind: SearchAdapterKind): boolean =>
30
+ SCOPES_VERSIONS[kind];