blume 1.7.3 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (690) hide show
  1. package/AGENTS.md +19 -0
  2. package/CHANGELOG.md +245 -0
  3. package/README.md +34 -21
  4. package/dist/cli/{chunk-vacwm2hv.js → chunk-27g6wdth.js} +2 -2
  5. package/dist/cli/{chunk-ps4m1xh4.js → chunk-2hn4b8z7.js} +513 -550
  6. package/dist/cli/chunk-2hn4b8z7.js.map +12 -0
  7. package/dist/cli/chunk-5shv93fd.js +39 -0
  8. package/dist/cli/chunk-5shv93fd.js.map +10 -0
  9. package/dist/cli/chunk-6crbhc3x.js +361 -0
  10. package/dist/cli/chunk-6crbhc3x.js.map +14 -0
  11. package/dist/cli/{chunk-8cjtbafj.js → chunk-6hsn950k.js} +109 -383
  12. package/dist/cli/chunk-6hsn950k.js.map +10 -0
  13. package/dist/cli/chunk-6vm74dry.js +148 -0
  14. package/dist/cli/chunk-6vm74dry.js.map +10 -0
  15. package/dist/cli/{chunk-yg63d42r.js → chunk-79jhk4py.js} +87 -58
  16. package/dist/cli/chunk-79jhk4py.js.map +35 -0
  17. package/dist/cli/chunk-82bbrxdn.js +51 -0
  18. package/dist/cli/chunk-82bbrxdn.js.map +10 -0
  19. package/dist/cli/chunk-abh8yjkn.js +31 -0
  20. package/dist/cli/chunk-abh8yjkn.js.map +10 -0
  21. package/dist/cli/chunk-ah61y8py.js +75 -0
  22. package/dist/cli/chunk-ah61y8py.js.map +11 -0
  23. package/dist/cli/{chunk-dwgcp5sm.js → chunk-ce574jw2.js} +1 -1
  24. package/dist/cli/chunk-ch6g3ar0.js +102 -0
  25. package/dist/cli/chunk-ch6g3ar0.js.map +10 -0
  26. package/dist/cli/chunk-dh8cwk36.js +279 -0
  27. package/dist/cli/chunk-dh8cwk36.js.map +10 -0
  28. package/dist/cli/{chunk-rqy0s5wh.js → chunk-epjnccmv.js} +17 -16
  29. package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-epjnccmv.js.map} +3 -3
  30. package/dist/cli/chunk-f2z5v128.js +97 -0
  31. package/dist/cli/chunk-f2z5v128.js.map +10 -0
  32. package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
  33. package/dist/cli/chunk-fa25z98p.js.map +11 -0
  34. package/dist/cli/{chunk-1jefwnfs.js → chunk-fs23ddbb.js} +1076 -2592
  35. package/dist/cli/chunk-fs23ddbb.js.map +35 -0
  36. package/dist/cli/{chunk-e7f42gdj.js → chunk-fxypxtvm.js} +2 -2
  37. package/dist/cli/{chunk-bvwwhd84.js → chunk-fz5wtpmh.js} +15 -15
  38. package/dist/cli/{chunk-bvwwhd84.js.map → chunk-fz5wtpmh.js.map} +1 -1
  39. package/dist/cli/chunk-hdpx1tax.js +91 -0
  40. package/dist/cli/chunk-hdpx1tax.js.map +10 -0
  41. package/dist/cli/{chunk-ct47dqpx.js → chunk-jts8mvcz.js} +67 -7
  42. package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
  43. package/dist/cli/{chunk-ahnw3kxw.js → chunk-jwyddg7y.js} +27 -22
  44. package/dist/cli/chunk-jwyddg7y.js.map +15 -0
  45. package/dist/cli/{chunk-cjtn640a.js → chunk-kdp5q7ke.js} +43 -20
  46. package/dist/cli/chunk-kdp5q7ke.js.map +10 -0
  47. package/dist/cli/{chunk-5g0w1e2c.js → chunk-kpf8rrjc.js} +28 -16
  48. package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-kpf8rrjc.js.map} +4 -4
  49. package/dist/cli/chunk-m3vmjgmq.js +133 -0
  50. package/dist/cli/chunk-m3vmjgmq.js.map +10 -0
  51. package/dist/cli/{chunk-b27xqwn9.js → chunk-mb2919y2.js} +9 -5
  52. package/dist/cli/chunk-mb2919y2.js.map +10 -0
  53. package/dist/cli/{chunk-5qk08vmp.js → chunk-q5163e60.js} +133 -54
  54. package/dist/cli/chunk-q5163e60.js.map +11 -0
  55. package/dist/cli/chunk-qkqwkpte.js +12437 -0
  56. package/dist/cli/chunk-qkqwkpte.js.map +182 -0
  57. package/dist/cli/{chunk-4x36ddpw.js → chunk-qs4q5p4e.js} +81 -87
  58. package/dist/cli/chunk-qs4q5p4e.js.map +10 -0
  59. package/dist/cli/{chunk-0xjyb285.js → chunk-qwsrynx5.js} +15 -5
  60. package/dist/cli/{chunk-0xjyb285.js.map → chunk-qwsrynx5.js.map} +4 -4
  61. package/dist/cli/chunk-s1p84fyh.js +261 -0
  62. package/dist/cli/chunk-s1p84fyh.js.map +10 -0
  63. package/dist/cli/chunk-s6jhgk0q.js +176 -0
  64. package/dist/cli/chunk-s6jhgk0q.js.map +11 -0
  65. package/dist/cli/chunk-vtk4a6dg.js +374 -0
  66. package/dist/cli/chunk-vtk4a6dg.js.map +10 -0
  67. package/dist/cli/{chunk-k79xp7av.js → chunk-wgm7m9qk.js} +230 -700
  68. package/dist/cli/chunk-wgm7m9qk.js.map +36 -0
  69. package/dist/cli/chunk-wm7js3j9.js +145 -0
  70. package/dist/cli/chunk-wm7js3j9.js.map +11 -0
  71. package/dist/cli/chunk-yt5n7ppj.js +79 -0
  72. package/dist/cli/chunk-yt5n7ppj.js.map +10 -0
  73. package/dist/cli/{chunk-3r45185y.js → chunk-yw7dm696.js} +9 -11
  74. package/dist/cli/{chunk-3r45185y.js.map → chunk-yw7dm696.js.map} +3 -3
  75. package/dist/cli/{chunk-nn13znc2.js → chunk-zxcczpyx.js} +1 -1
  76. package/dist/cli/chunk-zxh4d9vy.js +122 -0
  77. package/dist/cli/chunk-zxh4d9vy.js.map +11 -0
  78. package/dist/cli/index.js +214 -57
  79. package/dist/cli/index.js.map +8 -7
  80. package/dist/types/ai/agent-readability.d.ts +52 -0
  81. package/dist/types/ai/ai-catalog.d.ts +42 -0
  82. package/dist/types/ai/api/paths.d.ts +17 -0
  83. package/dist/types/ai/api-catalog.d.ts +18 -0
  84. package/dist/types/ai/ask-context.d.ts +7 -7
  85. package/dist/types/ai/ask.d.ts +368 -0
  86. package/dist/types/ai/changelog-markdown.d.ts +2 -0
  87. package/dist/types/ai/component-markdown.d.ts +2 -2
  88. package/dist/types/ai/index.d.ts +24 -0
  89. package/dist/types/ai/link-headers.d.ts +24 -0
  90. package/dist/types/ai/llms.d.ts +25 -0
  91. package/dist/types/ai/markdown.d.ts +45 -0
  92. package/dist/types/ai/mcp/discovery.d.ts +68 -0
  93. package/dist/types/ai/mcp/tools.d.ts +16 -0
  94. package/dist/types/ai/openapi-components.d.ts +43 -0
  95. package/dist/types/ai/relative-links.d.ts +26 -0
  96. package/dist/types/ai/serializers.d.ts +15 -0
  97. package/dist/types/ai/skills.d.ts +42 -0
  98. package/dist/types/ai/tar.d.ts +25 -0
  99. package/dist/types/ai/visibility.d.ts +17 -0
  100. package/dist/types/ai/web-bot-auth.d.ts +16 -0
  101. package/dist/types/analytics/adobe.d.ts +35 -0
  102. package/dist/types/analytics/amplitude.d.ts +50 -0
  103. package/dist/types/analytics/clarity.d.ts +31 -0
  104. package/dist/types/analytics/clearbit.d.ts +29 -0
  105. package/dist/types/analytics/cloudflare.d.ts +41 -0
  106. package/dist/types/analytics/fathom.d.ts +41 -0
  107. package/dist/types/analytics/google-analytics.d.ts +44 -0
  108. package/dist/types/analytics/google-tag-manager.d.ts +40 -0
  109. package/dist/types/analytics/head.d.ts +30 -0
  110. package/dist/types/analytics/heap.d.ts +40 -0
  111. package/dist/types/analytics/hightouch.d.ts +44 -0
  112. package/dist/types/analytics/hotjar.d.ts +33 -0
  113. package/dist/types/analytics/index.d.ts +61 -0
  114. package/dist/types/analytics/inline.d.ts +17 -0
  115. package/dist/types/analytics/logrocket.d.ts +44 -0
  116. package/dist/types/analytics/mixpanel.d.ts +67 -0
  117. package/dist/types/analytics/pirsch.d.ts +42 -0
  118. package/dist/types/analytics/plausible.d.ts +56 -0
  119. package/dist/types/analytics/posthog.d.ts +45 -0
  120. package/dist/types/analytics/schema.d.ts +320 -0
  121. package/dist/types/analytics/script.d.ts +46 -0
  122. package/dist/types/analytics/segment.d.ts +50 -0
  123. package/dist/types/analytics/vercel.d.ts +48 -0
  124. package/dist/types/astro/integration.d.ts +76 -0
  125. package/dist/types/astro/markdown-negotiation.d.ts +23 -0
  126. package/dist/types/astro/module-types.d.ts +14 -0
  127. package/dist/types/astro/pages.d.ts +44 -0
  128. package/dist/types/cli/env.d.ts +12 -0
  129. package/dist/types/cli/init/scaffold.d.ts +154 -0
  130. package/dist/types/components/layout/nav-utils.d.ts +11 -0
  131. package/dist/types/core/adapter.d.ts +47 -0
  132. package/dist/types/core/api-name.d.ts +7 -0
  133. package/dist/types/core/changelog-index.d.ts +13 -0
  134. package/dist/types/core/config-input.d.ts +197 -526
  135. package/dist/types/core/config.d.ts +61 -35
  136. package/dist/types/core/content-assets.d.ts +76 -0
  137. package/dist/types/core/custom-pages.d.ts +33 -0
  138. package/dist/types/core/data.d.ts +30 -15
  139. package/dist/types/core/define-components.d.ts +12 -9
  140. package/dist/types/core/deployment-env.d.ts +6 -11
  141. package/dist/types/core/frontmatter.d.ts +10 -0
  142. package/dist/types/core/graph.d.ts +18 -0
  143. package/dist/types/core/heading-markers.d.ts +54 -0
  144. package/dist/types/core/i18n-ui.d.ts +12 -10
  145. package/dist/types/core/i18n.d.ts +87 -0
  146. package/dist/types/core/includes.d.ts +138 -0
  147. package/dist/types/core/last-modified.d.ts +47 -0
  148. package/dist/types/core/links.d.ts +95 -0
  149. package/dist/types/core/locale-links.d.ts +60 -0
  150. package/dist/types/core/manifest.d.ts +17 -0
  151. package/dist/types/core/meta.d.ts +38 -0
  152. package/dist/types/core/nav-diagnostics.d.ts +26 -0
  153. package/dist/types/core/navigation.d.ts +6 -0
  154. package/dist/types/core/node-require.d.ts +19 -0
  155. package/dist/types/core/package-json.d.ts +13 -0
  156. package/dist/types/core/probe.d.ts +42 -0
  157. package/dist/types/core/project-graph.d.ts +51 -0
  158. package/dist/types/core/project.d.ts +2 -0
  159. package/dist/types/core/safe-href.d.ts +2 -0
  160. package/dist/types/core/safe-links.d.ts +26 -0
  161. package/dist/types/core/schema.d.ts +2284 -454
  162. package/dist/types/core/site-url.d.ts +16 -0
  163. package/dist/types/core/sources/assets.d.ts +36 -0
  164. package/dist/types/core/sources/cache.d.ts +37 -0
  165. package/dist/types/core/sources/collection.d.ts +28 -0
  166. package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
  167. package/dist/types/core/sources/contentful.d.ts +40 -0
  168. package/dist/types/core/sources/filesystem.d.ts +24 -0
  169. package/dist/types/core/sources/github-releases.d.ts +31 -0
  170. package/dist/types/core/sources/json.d.ts +30 -0
  171. package/dist/types/core/sources/lexical.d.ts +19 -0
  172. package/dist/types/core/sources/lower.d.ts +75 -0
  173. package/dist/types/core/sources/mdx-remote.d.ts +28 -0
  174. package/dist/types/core/sources/normalize.d.ts +147 -0
  175. package/dist/types/core/sources/notion.d.ts +131 -0
  176. package/dist/types/core/sources/obsidian.d.ts +46 -0
  177. package/dist/types/core/sources/payload.d.ts +39 -0
  178. package/dist/types/core/sources/portable-text.d.ts +42 -0
  179. package/dist/types/core/sources/read.d.ts +23 -0
  180. package/dist/types/core/sources/remote.d.ts +74 -0
  181. package/dist/types/core/sources/resolve.d.ts +19 -0
  182. package/dist/types/core/sources/sanity.d.ts +43 -0
  183. package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
  184. package/dist/types/core/sources/strapi.d.ts +33 -0
  185. package/dist/types/core/sources/types.d.ts +7 -0
  186. package/dist/types/core/sources/watch.d.ts +45 -0
  187. package/dist/types/core/text-width.d.ts +11 -0
  188. package/dist/types/core/types.d.ts +15 -1
  189. package/dist/types/core/unrecognized-keys.d.ts +7 -0
  190. package/dist/types/core/versions.d.ts +72 -0
  191. package/dist/types/core/yaml.d.ts +9 -0
  192. package/dist/types/deploy/adapter-output.d.ts +45 -0
  193. package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
  194. package/dist/types/deploy/adapters/index.d.ts +29 -0
  195. package/dist/types/deploy/adapters/netlify.d.ts +37 -0
  196. package/dist/types/deploy/adapters/node.d.ts +37 -0
  197. package/dist/types/deploy/adapters/registry.d.ts +133 -0
  198. package/dist/types/deploy/adapters/types.d.ts +71 -0
  199. package/dist/types/deploy/adapters/vercel.d.ts +38 -0
  200. package/dist/types/deploy/artifacts.d.ts +65 -0
  201. package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
  202. package/dist/types/deploy/function-bundle.d.ts +80 -0
  203. package/dist/types/deploy/headers.d.ts +50 -0
  204. package/dist/types/deploy/node-headers.d.ts +42 -0
  205. package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
  206. package/dist/types/deploy/platforms/index.d.ts +18 -0
  207. package/dist/types/deploy/platforms/netlify.d.ts +13 -0
  208. package/dist/types/deploy/platforms/node.d.ts +11 -0
  209. package/dist/types/deploy/platforms/paths.d.ts +27 -0
  210. package/dist/types/deploy/platforms/static.d.ts +10 -0
  211. package/dist/types/deploy/platforms/types.d.ts +104 -0
  212. package/dist/types/deploy/platforms/vercel.d.ts +32 -0
  213. package/dist/types/deploy/redirects.d.ts +53 -0
  214. package/dist/types/deploy/robots.d.ts +8 -0
  215. package/dist/types/deploy/rss.d.ts +31 -0
  216. package/dist/types/deploy/sitemap.d.ts +21 -0
  217. package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
  218. package/dist/types/markdown/code-title.d.ts +32 -0
  219. package/dist/types/markdown/fence-meta.d.ts +23 -0
  220. package/dist/types/markdown/themes.d.ts +3 -3
  221. package/dist/types/openapi/asyncapi.d.ts +129 -0
  222. package/dist/types/openapi/graphql-build.d.ts +8 -0
  223. package/dist/types/openapi/graphql.d.ts +122 -0
  224. package/dist/types/openapi/model.d.ts +158 -0
  225. package/dist/types/openapi/parse.d.ts +57 -0
  226. package/dist/types/openapi/references.d.ts +37 -25
  227. package/dist/types/openapi/render-mdx.d.ts +33 -0
  228. package/dist/types/openapi/sentence.d.ts +7 -0
  229. package/dist/types/openapi/signature.d.ts +10 -0
  230. package/dist/types/openapi/source.d.ts +22 -0
  231. package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
  232. package/dist/types/reference/asyncapi.d.ts +166 -0
  233. package/dist/types/reference/graphql.d.ts +181 -0
  234. package/dist/types/reference/index.d.ts +32 -0
  235. package/dist/types/reference/openapi.d.ts +165 -0
  236. package/dist/types/reference/options.d.ts +157 -0
  237. package/dist/types/reference/scalar.d.ts +136 -0
  238. package/dist/types/reference/schema.d.ts +630 -0
  239. package/dist/types/search/adapters/algolia.d.ts +32 -0
  240. package/dist/types/search/adapters/flexsearch.d.ts +12 -0
  241. package/dist/types/search/adapters/index.d.ts +31 -0
  242. package/dist/types/search/adapters/mixedbread.d.ts +22 -0
  243. package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
  244. package/dist/types/search/adapters/orama.d.ts +13 -0
  245. package/dist/types/search/adapters/pagefind.d.ts +12 -0
  246. package/dist/types/search/adapters/registry.d.ts +228 -0
  247. package/dist/types/search/adapters/types.d.ts +34 -0
  248. package/dist/types/search/adapters/typesense.d.ts +42 -0
  249. package/dist/types/search/build.d.ts +23 -0
  250. package/dist/types/search/documents.d.ts +90 -0
  251. package/dist/types/search/facets.d.ts +3 -0
  252. package/dist/types/search/orama-index.d.ts +1 -1
  253. package/dist/types/search/sync/algolia.d.ts +14 -0
  254. package/dist/types/search/sync/index.d.ts +14 -0
  255. package/dist/types/search/sync/orama-cloud.d.ts +10 -0
  256. package/dist/types/search/sync/typesense.d.ts +14 -0
  257. package/dist/types/sources/contentful.d.ts +68 -0
  258. package/dist/types/sources/custom.d.ts +20 -0
  259. package/dist/types/sources/filesystem.d.ts +42 -0
  260. package/dist/types/sources/github-releases.d.ts +46 -0
  261. package/dist/types/sources/index.d.ts +48 -0
  262. package/dist/types/sources/mdx-remote.d.ts +63 -0
  263. package/dist/types/sources/notion.d.ts +65 -0
  264. package/dist/types/sources/obsidian.d.ts +34 -0
  265. package/dist/types/sources/payload.d.ts +68 -0
  266. package/dist/types/sources/registry.d.ts +1414 -0
  267. package/dist/types/sources/sanity.d.ts +69 -0
  268. package/dist/types/sources/shared.d.ts +46 -0
  269. package/dist/types/sources/strapi.d.ts +66 -0
  270. package/dist/types/theme/icon-kind.d.ts +11 -0
  271. package/dist/types/theme/icons.d.ts +20 -0
  272. package/docs/01-quickstart.mdx +18 -18
  273. package/docs/02-deployment.mdx +52 -28
  274. package/docs/03-upgrading.mdx +364 -0
  275. package/docs/04-migrating.mdx +58 -0
  276. package/docs/08-faq.mdx +5 -5
  277. package/docs/advanced/blog.mdx +13 -6
  278. package/docs/advanced/changelog.mdx +23 -35
  279. package/docs/advanced/custom-pages.mdx +22 -10
  280. package/docs/advanced/meta.ts +1 -8
  281. package/docs/advanced/skills.mdx +8 -0
  282. package/docs/cli/audit.mdx +646 -0
  283. package/docs/cli/doctor.mdx +29 -0
  284. package/docs/{reference/eval.mdx → cli/evals.mdx} +12 -11
  285. package/docs/cli/index.mdx +105 -0
  286. package/docs/cli/meta.ts +7 -0
  287. package/docs/{reference → cli}/translate.mdx +9 -9
  288. package/docs/cli/validate.mdx +41 -0
  289. package/docs/cli/version.mdx +40 -0
  290. package/docs/configuration/analytics.mdx +350 -59
  291. package/docs/configuration/assistant.mdx +357 -0
  292. package/docs/configuration/customization.mdx +16 -10
  293. package/docs/configuration/index.mdx +50 -31
  294. package/docs/configuration/meta.ts +1 -1
  295. package/docs/configuration/search.mdx +76 -55
  296. package/docs/configuration/theming.mdx +24 -15
  297. package/docs/content/components.mdx +21 -5
  298. package/docs/{reference → content}/frontmatter.mdx +35 -1
  299. package/docs/content/i18n.mdx +9 -7
  300. package/docs/content/includes.mdx +2 -4
  301. package/docs/content/index.mdx +1 -1
  302. package/docs/content/islands.mdx +11 -6
  303. package/docs/content/meta.mdx +1 -1
  304. package/docs/content/meta.ts +1 -0
  305. package/docs/content/navigation.mdx +9 -7
  306. package/docs/content/sources.mdx +145 -50
  307. package/docs/content/syntax.mdx +16 -12
  308. package/docs/content/versioning.mdx +3 -3
  309. package/docs/discoverability/agent-discovery.mdx +12 -12
  310. package/docs/discoverability/index.mdx +4 -4
  311. package/docs/discoverability/json-api.mdx +4 -4
  312. package/docs/discoverability/llms-txt.mdx +6 -6
  313. package/docs/discoverability/markdown.mdx +4 -4
  314. package/docs/discoverability/mcp.mdx +11 -11
  315. package/docs/discoverability/sitemap-and-robots.mdx +3 -3
  316. package/docs/index.mdx +4 -4
  317. package/docs/references/asyncapi.mdx +59 -0
  318. package/docs/{advanced → references}/graphql.mdx +45 -32
  319. package/docs/{reference → references}/meta.ts +2 -2
  320. package/docs/references/openapi.mdx +171 -0
  321. package/docs/references/scalar.mdx +64 -0
  322. package/package.json +42 -8
  323. package/skills/blume/SKILL.md +23 -10
  324. package/skills/blume-migrate/SKILL.md +22 -21
  325. package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
  326. package/skills/blume-migrate/references/docusaurus.md +5 -4
  327. package/skills/blume-migrate/references/fumadocs.md +4 -4
  328. package/skills/blume-migrate/references/mintlify.md +23 -8
  329. package/skills/blume-migrate/references/monorepo.md +6 -6
  330. package/skills/blume-migrate/references/starlight.md +4 -4
  331. package/src/ai/agent-readability.ts +25 -26
  332. package/src/ai/ai-catalog.ts +50 -32
  333. package/src/ai/api/handlers.ts +46 -11
  334. package/src/ai/api/paths.ts +1 -1
  335. package/src/ai/api-catalog.ts +8 -8
  336. package/src/ai/ask-context.ts +7 -7
  337. package/src/ai/ask-data.ts +3 -3
  338. package/src/ai/ask.ts +637 -100
  339. package/src/ai/changelog-markdown.ts +91 -0
  340. package/src/ai/component-markdown.ts +328 -12
  341. package/src/ai/cors.ts +3 -3
  342. package/src/ai/index.ts +45 -0
  343. package/src/ai/link-headers.ts +7 -6
  344. package/src/ai/llms.ts +20 -15
  345. package/src/ai/markdown.ts +35 -5
  346. package/src/ai/mcp/data.ts +9 -5
  347. package/src/ai/openapi-components.ts +5 -2
  348. package/src/ai/relative-links.ts +170 -0
  349. package/src/ai/serializers.ts +3 -3
  350. package/src/ai/skills.ts +1 -1
  351. package/src/ai/visibility.ts +1 -1
  352. package/src/ai/web-bot-auth.ts +2 -2
  353. package/src/analytics/adobe.ts +46 -0
  354. package/src/analytics/amplitude.ts +79 -0
  355. package/src/analytics/clarity.ts +46 -0
  356. package/src/analytics/clearbit.ts +47 -0
  357. package/src/analytics/cloudflare.ts +67 -0
  358. package/src/analytics/fathom.ts +64 -0
  359. package/src/analytics/google-analytics.ts +84 -0
  360. package/src/analytics/google-tag-manager.ts +61 -0
  361. package/src/analytics/head.ts +130 -0
  362. package/src/analytics/heap.ts +65 -0
  363. package/src/analytics/hightouch.ts +77 -0
  364. package/src/analytics/hotjar.ts +47 -0
  365. package/src/analytics/index.ts +71 -0
  366. package/src/analytics/inline.ts +21 -0
  367. package/src/analytics/logrocket.ts +71 -0
  368. package/src/analytics/mixpanel.ts +92 -0
  369. package/src/analytics/pirsch.ts +66 -0
  370. package/src/analytics/plausible.ts +83 -0
  371. package/src/analytics/posthog.ts +78 -0
  372. package/src/analytics/schema.ts +60 -0
  373. package/src/analytics/script.ts +60 -0
  374. package/src/analytics/segment.ts +85 -0
  375. package/src/analytics/vercel.ts +50 -0
  376. package/src/astro/adapter-root.ts +7 -9
  377. package/src/astro/component-slots.ts +131 -91
  378. package/src/astro/generate.ts +129 -361
  379. package/src/astro/integration.ts +2 -6
  380. package/src/astro/module-types.ts +1 -1
  381. package/src/astro/pages.ts +13 -101
  382. package/src/astro/render-deps.ts +379 -0
  383. package/src/astro/runtime-deps.ts +201 -0
  384. package/src/astro/templates.ts +575 -562
  385. package/src/audit/agent.ts +24 -0
  386. package/src/audit/catalog.ts +2 -2
  387. package/src/audit/checks/assets.ts +2 -2
  388. package/src/audit/checks/dns-aid.ts +1 -1
  389. package/src/audit/checks/duplicates.ts +3 -1
  390. package/src/audit/checks/i18n.ts +1 -1
  391. package/src/audit/checks/indexability.ts +7 -7
  392. package/src/audit/checks/links.ts +2 -2
  393. package/src/audit/checks/llms.ts +6 -6
  394. package/src/audit/checks/network.ts +3 -3
  395. package/src/audit/checks/og-image.ts +2 -2
  396. package/src/audit/checks/robots.ts +1 -1
  397. package/src/audit/checks/sitemap.ts +2 -2
  398. package/src/audit/checks/social.ts +1 -1
  399. package/src/audit/run.ts +4 -3
  400. package/src/audit/terms.ts +31 -0
  401. package/src/audit/url.ts +13 -13
  402. package/src/blume-modules.d.ts +2 -2
  403. package/src/cli/command-meta.ts +10 -0
  404. package/src/cli/commands/audit.ts +40 -21
  405. package/src/cli/commands/build.ts +71 -316
  406. package/src/cli/commands/check.ts +1 -0
  407. package/src/cli/commands/dev.ts +40 -1
  408. package/src/cli/commands/doctor.ts +92 -14
  409. package/src/cli/commands/eject.ts +44 -7
  410. package/src/cli/commands/eval.ts +5 -5
  411. package/src/cli/commands/init.ts +161 -41
  412. package/src/cli/commands/migrate.ts +121 -0
  413. package/src/cli/commands/preview.ts +7 -1
  414. package/src/cli/commands/translate.ts +5 -5
  415. package/src/cli/commands/upgrade.ts +141 -0
  416. package/src/cli/commands/version.ts +57 -44
  417. package/src/cli/eject-scripts.ts +121 -6
  418. package/src/cli/index.ts +11 -1
  419. package/src/cli/init/install.ts +70 -0
  420. package/src/cli/init/questions.ts +7 -0
  421. package/src/cli/init/scaffold.ts +459 -75
  422. package/src/cli/lazy-command.ts +37 -1
  423. package/src/cli/prepare.ts +40 -6
  424. package/src/cli/required-secrets.ts +39 -12
  425. package/src/cli/unknown-flags.ts +266 -0
  426. package/src/cli/yarn-pnp.ts +52 -0
  427. package/src/components/content/AccordionItem.astro +7 -1
  428. package/src/components/content/Card.astro +4 -3
  429. package/src/components/content/ColorItem.astro +22 -4
  430. package/src/components/content/GithubInfo.astro +2 -2
  431. package/src/components/content/Prompt.astro +25 -25
  432. package/src/components/content/Tabs.astro +3 -1
  433. package/src/components/content/Tile.astro +2 -3
  434. package/src/components/content/Tooltip.astro +57 -9
  435. package/src/components/content/content-strings.ts +34 -0
  436. package/src/components/content/diff.ts +1 -1
  437. package/src/components/content/mermaid-element.ts +13 -2
  438. package/src/components/content/prompt-markdown.ts +292 -0
  439. package/src/components/content/tooltip-id.ts +41 -0
  440. package/src/components/copy-feedback.ts +1 -1
  441. package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
  442. package/src/components/islands/{ask-ai.tsx → assistant.tsx} +23 -23
  443. package/src/components/islands/hooks.ts +36 -11
  444. package/src/components/layout/Analytics.astro +21 -79
  445. package/src/components/layout/Banner.astro +3 -1
  446. package/src/components/layout/DiscoveryLinks.astro +69 -0
  447. package/src/components/layout/Header.astro +93 -30
  448. package/src/components/layout/LanguageSwitcher.astro +4 -1
  449. package/src/components/layout/Logo.astro +23 -2
  450. package/src/components/layout/NavSelector.astro +13 -2
  451. package/src/components/layout/NavTree.astro +12 -3
  452. package/src/components/layout/NavTreeScript.astro +17 -3
  453. package/src/components/layout/PageActions.astro +3 -3
  454. package/src/components/layout/PageFeedback.astro +11 -1
  455. package/src/components/layout/PageLayout.astro +58 -11
  456. package/src/components/layout/Pagination.astro +7 -7
  457. package/src/components/layout/ReferenceLayout.astro +22 -13
  458. package/src/components/layout/RootLayout.astro +75 -72
  459. package/src/components/layout/Search.astro +43 -19
  460. package/src/components/layout/WebMcp.astro +1 -1
  461. package/src/components/layout/analytics-client.ts +73 -16
  462. package/src/components/layout/drawer-inert.ts +113 -15
  463. package/src/components/layout/dropdown-clamp.ts +105 -0
  464. package/src/components/layout/head-scripts.ts +15 -6
  465. package/src/components/layout/nav-utils.ts +17 -0
  466. package/src/components/layout/search/algolia.ts +8 -8
  467. package/src/components/layout/search/orama-cloud.ts +9 -7
  468. package/src/components/layout/search/typesense.ts +11 -17
  469. package/src/components/openapi/MessageComposer.astro +2 -2
  470. package/src/components/openapi/Playground.astro +2 -2
  471. package/src/components/openapi/description.ts +2 -2
  472. package/src/components/openapi/playground-client.ts +79 -10
  473. package/src/core/changelog-index.ts +24 -0
  474. package/src/core/code-fences.ts +1 -1
  475. package/src/core/component-overrides.ts +399 -154
  476. package/src/core/config-input.ts +201 -566
  477. package/src/core/config.ts +131 -42
  478. package/src/core/custom-pages.ts +105 -0
  479. package/src/core/data.ts +34 -15
  480. package/src/core/define-components.ts +12 -9
  481. package/src/core/deployment-env.ts +18 -74
  482. package/src/core/diagnostics.ts +14 -7
  483. package/src/core/graph.ts +69 -25
  484. package/src/core/i18n-ui.ts +41 -11
  485. package/src/core/i18n.ts +17 -0
  486. package/src/core/includes.ts +156 -38
  487. package/src/core/last-modified.ts +6 -11
  488. package/src/core/links.ts +166 -2
  489. package/src/core/manifest.ts +10 -3
  490. package/src/core/navigation.ts +115 -16
  491. package/src/core/new-tab.ts +35 -0
  492. package/src/core/node-require.ts +21 -0
  493. package/src/core/project-graph.ts +42 -26
  494. package/src/core/project.ts +9 -4
  495. package/src/core/request-body.ts +61 -0
  496. package/src/core/safe-href.ts +28 -0
  497. package/src/core/safe-links.ts +68 -0
  498. package/src/core/schema.ts +528 -745
  499. package/src/core/server-features.ts +10 -11
  500. package/src/core/sources/assets.ts +47 -11
  501. package/src/core/sources/collection.ts +67 -0
  502. package/src/core/sources/contentful-rich-text.ts +285 -0
  503. package/src/core/sources/contentful.ts +173 -0
  504. package/src/core/sources/github-releases.ts +51 -1
  505. package/src/core/sources/json.ts +71 -0
  506. package/src/core/sources/lexical.ts +195 -0
  507. package/src/core/sources/lower.ts +226 -0
  508. package/src/core/sources/normalize.ts +52 -2
  509. package/src/core/sources/notion.ts +39 -28
  510. package/src/core/sources/payload.ts +135 -0
  511. package/src/core/sources/portable-text.ts +11 -16
  512. package/src/core/sources/remote.ts +226 -0
  513. package/src/core/sources/resolve.ts +104 -166
  514. package/src/core/sources/sanity.ts +16 -49
  515. package/src/core/sources/strapi-blocks.ts +124 -0
  516. package/src/core/sources/strapi.ts +191 -0
  517. package/src/core/sources/types.ts +12 -1
  518. package/src/core/types.ts +15 -1
  519. package/src/core/ui-packs/ar.ts +10 -7
  520. package/src/core/ui-packs/bg.ts +10 -7
  521. package/src/core/ui-packs/bn.ts +10 -7
  522. package/src/core/ui-packs/ca.ts +7 -6
  523. package/src/core/ui-packs/cs.ts +10 -7
  524. package/src/core/ui-packs/da.ts +10 -7
  525. package/src/core/ui-packs/de.ts +10 -7
  526. package/src/core/ui-packs/el.ts +7 -6
  527. package/src/core/ui-packs/es.ts +7 -6
  528. package/src/core/ui-packs/fa.ts +10 -7
  529. package/src/core/ui-packs/fi.ts +10 -7
  530. package/src/core/ui-packs/fr.ts +7 -6
  531. package/src/core/ui-packs/he.ts +10 -7
  532. package/src/core/ui-packs/hi.ts +10 -7
  533. package/src/core/ui-packs/hr.ts +10 -7
  534. package/src/core/ui-packs/hu.ts +10 -7
  535. package/src/core/ui-packs/id.ts +10 -7
  536. package/src/core/ui-packs/it.ts +7 -6
  537. package/src/core/ui-packs/ja.ts +7 -6
  538. package/src/core/ui-packs/ko.ts +7 -6
  539. package/src/core/ui-packs/nl.ts +10 -7
  540. package/src/core/ui-packs/no.ts +10 -7
  541. package/src/core/ui-packs/pl.ts +10 -7
  542. package/src/core/ui-packs/pt-br.ts +7 -6
  543. package/src/core/ui-packs/pt.ts +7 -6
  544. package/src/core/ui-packs/ro.ts +10 -7
  545. package/src/core/ui-packs/ru.ts +10 -7
  546. package/src/core/ui-packs/sk.ts +10 -7
  547. package/src/core/ui-packs/sr.ts +10 -7
  548. package/src/core/ui-packs/sv.ts +10 -7
  549. package/src/core/ui-packs/th.ts +7 -6
  550. package/src/core/ui-packs/tr.ts +10 -7
  551. package/src/core/ui-packs/uk.ts +10 -7
  552. package/src/core/ui-packs/vi.ts +7 -6
  553. package/src/core/ui-packs/zh-tw.ts +7 -6
  554. package/src/core/ui-packs/zh.ts +7 -6
  555. package/src/core/unrecognized-keys.ts +10 -0
  556. package/src/core/version-cut.ts +116 -8
  557. package/src/deploy/adapter-output.ts +57 -97
  558. package/src/deploy/adapters/cloudflare.ts +39 -0
  559. package/src/deploy/adapters/index.ts +41 -0
  560. package/src/deploy/adapters/netlify.ts +34 -0
  561. package/src/deploy/adapters/node.ts +34 -0
  562. package/src/deploy/adapters/registry.ts +127 -0
  563. package/src/deploy/adapters/types.ts +92 -0
  564. package/src/deploy/adapters/vercel.ts +35 -0
  565. package/src/deploy/artifacts.ts +55 -27
  566. package/src/deploy/cloudflare-negotiation.ts +179 -100
  567. package/src/deploy/function-bundle.ts +18 -3
  568. package/src/deploy/headers.ts +124 -23
  569. package/src/deploy/node-headers.ts +198 -0
  570. package/src/deploy/platforms/cloudflare.ts +312 -0
  571. package/src/deploy/platforms/index.ts +67 -0
  572. package/src/deploy/platforms/netlify.ts +52 -0
  573. package/src/deploy/platforms/node.ts +40 -0
  574. package/src/deploy/platforms/paths.ts +42 -0
  575. package/src/deploy/platforms/static.ts +29 -0
  576. package/src/deploy/platforms/types.ts +112 -0
  577. package/src/deploy/platforms/vercel.ts +193 -0
  578. package/src/deploy/redirects.ts +30 -18
  579. package/src/deploy/robots.ts +3 -3
  580. package/src/deploy/rss.ts +2 -2
  581. package/src/deploy/sitemap.ts +2 -2
  582. package/src/deploy/vercel-negotiation.ts +2 -2
  583. package/src/eval/agents.ts +32 -1
  584. package/src/eval/findings.ts +19 -11
  585. package/src/eval/report.ts +10 -2
  586. package/src/markdown/external-links.ts +65 -0
  587. package/src/markdown/include.ts +45 -27
  588. package/src/markdown/index.ts +34 -9
  589. package/src/markdown/inline-code.ts +12 -6
  590. package/src/markdown/relative-links.ts +324 -0
  591. package/src/markdown/themes.ts +3 -3
  592. package/src/migrate/migrate.ts +149 -0
  593. package/src/openapi/parse.ts +64 -16
  594. package/src/openapi/proxy.ts +62 -10
  595. package/src/openapi/references.ts +147 -147
  596. package/src/openapi/render-mdx.ts +32 -10
  597. package/src/openapi/scalar.ts +15 -13
  598. package/src/openapi/sentence.ts +14 -0
  599. package/src/openapi/source.ts +37 -21
  600. package/src/openapi/spec-dependency-error.ts +15 -0
  601. package/src/reference/asyncapi.ts +83 -0
  602. package/src/reference/graphql.ts +89 -0
  603. package/src/reference/index.ts +40 -0
  604. package/src/reference/openapi.ts +83 -0
  605. package/src/reference/options.ts +201 -0
  606. package/src/reference/scalar.ts +136 -0
  607. package/src/reference/schema.ts +88 -0
  608. package/src/registry/eject.ts +109 -53
  609. package/src/search/adapters/algolia.ts +46 -0
  610. package/src/search/adapters/flexsearch.ts +29 -0
  611. package/src/search/adapters/index.ts +39 -0
  612. package/src/search/adapters/mixedbread.ts +39 -0
  613. package/src/search/adapters/orama-cloud.ts +51 -0
  614. package/src/search/adapters/orama.ts +24 -0
  615. package/src/search/adapters/pagefind.ts +27 -0
  616. package/src/search/adapters/registry.ts +131 -0
  617. package/src/search/adapters/types.ts +46 -0
  618. package/src/search/adapters/typesense.ts +57 -0
  619. package/src/search/build.ts +8 -4
  620. package/src/search/documents.ts +8 -2
  621. package/src/search/orama-index.ts +1 -1
  622. package/src/search/sync/algolia.ts +12 -11
  623. package/src/search/sync/index.ts +35 -20
  624. package/src/search/sync/orama-cloud.ts +12 -9
  625. package/src/search/sync/typesense.ts +15 -13
  626. package/src/sources/contentful.ts +63 -0
  627. package/src/sources/custom.ts +38 -0
  628. package/src/sources/filesystem.ts +51 -0
  629. package/src/sources/github-releases.ts +52 -0
  630. package/src/sources/index.ts +60 -0
  631. package/src/sources/mdx-remote.ts +76 -0
  632. package/src/sources/notion.ts +63 -0
  633. package/src/sources/obsidian.ts +38 -0
  634. package/src/sources/payload.ts +60 -0
  635. package/src/sources/registry.ts +182 -0
  636. package/src/sources/sanity.ts +66 -0
  637. package/src/sources/shared.ts +52 -0
  638. package/src/sources/strapi.ts +58 -0
  639. package/src/theme/entry.ts +24 -2
  640. package/src/translate/report.ts +40 -7
  641. package/src/upgrade/upgrade.ts +499 -0
  642. package/dist/cli/chunk-0qymqwzz.js +0 -164
  643. package/dist/cli/chunk-0qymqwzz.js.map +0 -15
  644. package/dist/cli/chunk-1jefwnfs.js.map +0 -48
  645. package/dist/cli/chunk-2mzebbbz.js +0 -69
  646. package/dist/cli/chunk-2z47ypj8.js.map +0 -11
  647. package/dist/cli/chunk-4x36ddpw.js.map +0 -11
  648. package/dist/cli/chunk-5093q3n7.js +0 -68
  649. package/dist/cli/chunk-5093q3n7.js.map +0 -10
  650. package/dist/cli/chunk-5qk08vmp.js.map +0 -11
  651. package/dist/cli/chunk-7s8hm3b6.js +0 -5347
  652. package/dist/cli/chunk-7s8hm3b6.js.map +0 -58
  653. package/dist/cli/chunk-8cjtbafj.js.map +0 -13
  654. package/dist/cli/chunk-97r59kpr.js +0 -381
  655. package/dist/cli/chunk-97r59kpr.js.map +0 -12
  656. package/dist/cli/chunk-ahnw3kxw.js.map +0 -15
  657. package/dist/cli/chunk-b27xqwn9.js.map +0 -10
  658. package/dist/cli/chunk-bf6bt1xt.js +0 -185
  659. package/dist/cli/chunk-bf6bt1xt.js.map +0 -11
  660. package/dist/cli/chunk-cjtn640a.js.map +0 -10
  661. package/dist/cli/chunk-ct47dqpx.js.map +0 -11
  662. package/dist/cli/chunk-esphfr8p.js +0 -107
  663. package/dist/cli/chunk-esphfr8p.js.map +0 -11
  664. package/dist/cli/chunk-ex56aa81.js +0 -1016
  665. package/dist/cli/chunk-ex56aa81.js.map +0 -13
  666. package/dist/cli/chunk-garjf5z9.js +0 -30
  667. package/dist/cli/chunk-garjf5z9.js.map +0 -10
  668. package/dist/cli/chunk-js7saxwm.js +0 -1045
  669. package/dist/cli/chunk-js7saxwm.js.map +0 -22
  670. package/dist/cli/chunk-k79xp7av.js.map +0 -39
  671. package/dist/cli/chunk-ps4m1xh4.js.map +0 -15
  672. package/dist/cli/chunk-q4rae3bg.js +0 -60
  673. package/dist/cli/chunk-q4rae3bg.js.map +0 -10
  674. package/dist/cli/chunk-rz9jmfhz.js +0 -108
  675. package/dist/cli/chunk-rz9jmfhz.js.map +0 -10
  676. package/dist/cli/chunk-vh9w1sgp.js +0 -73
  677. package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
  678. package/dist/cli/chunk-vrfp10qk.js +0 -81
  679. package/dist/cli/chunk-vrfp10qk.js.map +0 -10
  680. package/dist/cli/chunk-yg63d42r.js.map +0 -34
  681. package/docs/advanced/api-reference.mdx +0 -240
  682. package/docs/configuration/ask-ai.mdx +0 -256
  683. package/docs/reference/cli.mdx +0 -197
  684. package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
  685. package/src/components/content/changelog-element.ts +0 -69
  686. package/src/search/providers.ts +0 -91
  687. /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-27g6wdth.js.map} +0 -0
  688. /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-ce574jw2.js.map} +0 -0
  689. /package/dist/cli/{chunk-e7f42gdj.js.map → chunk-fxypxtvm.js.map} +0 -0
  690. /package/dist/cli/{chunk-nn13znc2.js.map → chunk-zxcczpyx.js.map} +0 -0
@@ -13,22 +13,14 @@ import { createRequire } from "node:module";
13
13
  import { pathToFileURL } from "node:url";
14
14
 
15
15
  import pMap from "p-map";
16
- import {
17
- basename,
18
- dirname,
19
- isAbsolute,
20
- join,
21
- normalize,
22
- relative,
23
- resolve,
24
- } from "pathe";
16
+ import { dirname, isAbsolute, join, normalize, relative, resolve } from "pathe";
25
17
  import { glob } from "tinyglobby";
26
18
 
27
19
  import { hasAiCatalog } from "../ai/ai-catalog.ts";
28
20
  import { OPENAPI_PATH } from "../ai/api/paths.ts";
29
21
  import { buildApiSpec } from "../ai/api/spec.ts";
30
22
  import { buildAskData } from "../ai/ask-data.ts";
31
- import { askBackendRuntimeDep, resolveAskBackend } from "../ai/ask.ts";
23
+ import { resolveAskBackend } from "../ai/ask.ts";
32
24
  import { buildHomeLinkHeader } from "../ai/link-headers.ts";
33
25
  import { buildRawMarkdown, markdownRoutePaths } from "../ai/markdown.ts";
34
26
  import type { RawMarkdownEntry } from "../ai/markdown.ts";
@@ -41,7 +33,11 @@ import {
41
33
  } from "../components/layout/nav-utils.ts";
42
34
  import { normalizeBasePath } from "../core/base-path.ts";
43
35
  import { validateUsedComponents } from "../core/component-diagnostics.ts";
44
- import { analyzeComponentOverrides } from "../core/component-overrides.ts";
36
+ import {
37
+ analyzeComponentOverrides,
38
+ emptyComponentOverrides,
39
+ } from "../core/component-overrides.ts";
40
+ import type { ComponentOverrideAnalysis } from "../core/component-overrides.ts";
45
41
  import {
46
42
  collectContentAssets,
47
43
  rewriteRelativeImages,
@@ -87,7 +83,7 @@ import type { DerivedOgFonts } from "../og/derive.ts";
87
83
  import { resolveOgLogo } from "../og/logo.ts";
88
84
  import type { ApiSpecData, OpenApiData } from "../openapi/model.ts";
89
85
  import {
90
- builtinProxyKinds,
86
+ builtinProxyReferences,
91
87
  hasScalarReferences,
92
88
  needsPlaygroundProxy,
93
89
  referenceRoutes,
@@ -97,7 +93,6 @@ import { isOpenApiSource } from "../openapi/source.ts";
97
93
  import { registry } from "../registry/registry.ts";
98
94
  import { buildSearchDocuments } from "../search/documents.ts";
99
95
  import { resolveSearchPopular } from "../search/popular.ts";
100
- import { searchProviderMeta, servesStaticIndex } from "../search/providers.ts";
101
96
  import {
102
97
  examplesEntryTemplate,
103
98
  tailwindEntryTemplate,
@@ -111,7 +106,6 @@ import { buildThemeCss } from "../theme/palette.ts";
111
106
  import { rebaseSourceDirectives } from "../theme/sources.ts";
112
107
  import { twoslashCss } from "../theme/twoslash.ts";
113
108
  import { planComponentSlots } from "./component-slots.ts";
114
- import type { ComponentSlotPlan } from "./component-slots.ts";
115
109
  import {
116
110
  EXAMPLE_SCAN_GLOB,
117
111
  discoverExamples,
@@ -126,6 +120,8 @@ import {
126
120
  hasGeneratedChangelog,
127
121
  routeIsTaken,
128
122
  } from "./pages.ts";
123
+ import { candidateHolding } from "./render-deps.ts";
124
+ import { missingDependencyDiagnostic } from "./runtime-deps.ts";
129
125
  import { publishRuntimeModules } from "./runtime-modules.ts";
130
126
  import type { RuntimeModuleId } from "./runtime-modules.ts";
131
127
  import {
@@ -140,8 +136,6 @@ import {
140
136
  exampleWrapperTemplate,
141
137
  examplesPageTemplate,
142
138
  exampleSlug,
143
- islandMapTemplate,
144
- islandWrapperTemplate,
145
139
  apiNavigationTemplate,
146
140
  apiNotFoundTemplate,
147
141
  apiPageTemplate,
@@ -169,19 +163,14 @@ import {
169
163
  } from "./templates.ts";
170
164
  import type { ClientFeatures } from "./templates.ts";
171
165
 
166
+ // The render-deps plugin and the dependency-directory probe live in
167
+ // `render-deps.ts`; `blume/astro` and existing callers import them from here.
168
+ export { blumeDepsDir, prerenderDepsPlugin } from "./render-deps.ts";
169
+ export type { PrerenderDepsPlugin } from "./render-deps.ts";
170
+
172
171
  /** Absolute path to the Blume package `src` directory. */
173
172
  const BLUME_SRC = join(packageRoot(), "src");
174
173
 
175
- /** Whether a module specifier resolves from a directory via node resolution. */
176
- const canResolveFrom = (fromDir: string, spec: string): boolean => {
177
- try {
178
- createRequire(pathToFileURL(join(fromDir, "_.js")).href).resolve(spec);
179
- return true;
180
- } catch {
181
- return false;
182
- }
183
- };
184
-
185
174
  /**
186
175
  * Absolute path to `babel-plugin-react-compiler`, resolved from Blume's own
187
176
  * package root (Blume ships it). Returns null when React or the compiler is off.
@@ -281,62 +270,6 @@ export const sameRealDir = (a: string, b: string): boolean => {
281
270
  }
282
271
  };
283
272
 
284
- /**
285
- * The two places an installer can put Blume's dependencies:
286
- * - `<blume>/node_modules` — deps nested under the package (workspace source,
287
- * or npm nesting them away from a conflicting hoisted copy)
288
- * - `dirname(<blume>)` — deps as siblings in the store (isolated/pnpm)
289
- *
290
- * `packageRoot()` resolves to Blume's real on-disk path (Node follows the
291
- * install symlink), so its parent is the store's package directory where the
292
- * isolated linker places the siblings.
293
- */
294
- const depsCandidates = (pkgDir: string): string[] => [
295
- join(pkgDir, "node_modules"),
296
- dirname(pkgDir),
297
- ];
298
-
299
- /** First dependency candidate containing the package dir `segments`, or null. */
300
- const candidateHolding = (
301
- pkgDir: string,
302
- ...segments: string[]
303
- ): string | null =>
304
- depsCandidates(pkgDir).find((dir) => existsSync(join(dir, ...segments))) ??
305
- null;
306
-
307
- /**
308
- * Locate the directory that holds Blume's installed dependencies (Astro and its
309
- * integrations).
310
- *
311
- * With a clean hoisted install this is moot — the deps sit in a `node_modules`
312
- * the generated `.blume/` already walks up into, and {@link ensureDepsLink}
313
- * short-circuits before we need it. But under isolated linkers (Bun's
314
- * `isolated` mode, pnpm) Blume's deps are NOT hoisted into the project; they
315
- * live beside the Blume package in a virtual store, invisible to the upward
316
- * walk from `.blume/` — so probe the {@link depsCandidates}.
317
- *
318
- * Astro alone is a bad probe: an npm split install (an `overrides` pin plus an
319
- * incremental install) hoists `astro` to the project root while Blume's other
320
- * deps stay nested, and probing for astro then picks the root directory — one
321
- * that holds none of them. Prefer a candidate with the full set (astro beside
322
- * `@astrojs/mdx`, the integration every generated runtime declares), then one
323
- * with the integrations (astro hoisted away — the rest of Blume's deps sit
324
- * there too), then one with astro alone.
325
- */
326
- const holdsAstro = (dir: string): boolean => existsSync(join(dir, "astro"));
327
- const holdsMdx = (dir: string): boolean =>
328
- existsSync(join(dir, "@astrojs", "mdx"));
329
-
330
- export const blumeDepsDir = (pkgDir: string = packageRoot()): string | null => {
331
- const candidates = depsCandidates(pkgDir);
332
- return (
333
- candidates.find((dir) => holdsAstro(dir) && holdsMdx(dir)) ??
334
- candidates.find(holdsMdx) ??
335
- candidates.find(holdsAstro) ??
336
- null
337
- );
338
- };
339
-
340
273
  /**
341
274
  * Create `link` as a directory symlink to `target`, falling back to a junction.
342
275
  *
@@ -554,169 +487,6 @@ export const ensureDepsLink = async (
554
487
  return astroConflictWarning(blumeAstro, outDirHit?.pkg ?? null);
555
488
  };
556
489
 
557
- /**
558
- * Vite plugin that makes Blume's externalized runtime deps (zod, shiki, sharp,
559
- * `takumi-js`, …) resolvable when Astro executes the static prerender
560
- * bundle under an isolated linker (Bun's `isolated` mode, pnpm).
561
- *
562
- * Astro's static build emits a self-contained SSR bundle to
563
- * `<outDir>/.prerender/` and `import()`s it in-process to generate the HTML.
564
- * That bundle externalizes Blume's render-time deps, so Node resolves them at
565
- * prerender time by walking up from `.prerender/chunks/*.mjs`. {@link
566
- * ensureDepsLink} only repairs resolution rooted at `.blume/`; `.prerender/`
567
- * lives under `dist/`, a separate tree an isolated linker never hoists Blume's
568
- * deps into — so the import dies with `Cannot find package 'zod'`. We drop the
569
- * same `node_modules` junction into the prerender root, mirroring
570
- * `.blume/node_modules`, so every externalized specifier — native bindings
571
- * included, which can't be bundled — resolves. Astro deletes `.prerender/` once
572
- * generation finishes (and the junction with it: `fs.rm` unlinks symlinks, it
573
- * never follows them), so nothing leaks into the published `dist/`.
574
- *
575
- * Keyed off the output dir's basename (`.prerender`) — the name Astro 7 gives
576
- * the prerender build for both static (`<outDir>/.prerender/`) and server
577
- * (`<build.server>/.prerender/`) output — so it fires for exactly that build.
578
- * Inert in dev, where there is no build and `writeBundle` never runs.
579
- */
580
- export interface PrerenderDepsPlugin {
581
- name: string;
582
- writeBundle: (options: { dir?: string }) => Promise<void>;
583
- }
584
-
585
- export const prerenderDepsPlugin = (
586
- pkgDir: string = packageRoot()
587
- ): PrerenderDepsPlugin => ({
588
- name: "blume:prerender-deps",
589
- writeBundle: async (options) => {
590
- if (!options.dir || basename(options.dir) !== ".prerender") {
591
- return;
592
- }
593
- const depsDir = blumeDepsDir(pkgDir);
594
- if (!depsDir) {
595
- return;
596
- }
597
- await linkDepsJunction(join(options.dir, "node_modules"), depsDir);
598
- },
599
- });
600
-
601
- /** Astro integration package each non-React island framework needs installed. */
602
- const ISLAND_FRAMEWORK_DEPS = new Map([
603
- ["svelte", "@astrojs/svelte"],
604
- ["vue", "@astrojs/vue"],
605
- ]);
606
-
607
- /**
608
- * Adapter package the project must install itself for each deployment
609
- * platform whose adapter Blume doesn't ship. Node and Vercel ship with Blume,
610
- * so they never need this.
611
- */
612
- const DEPLOYMENT_ADAPTER_DEPS = new Map([
613
- ["cloudflare", "@astrojs/cloudflare"],
614
- ["netlify", "@astrojs/netlify"],
615
- ]);
616
-
617
- /**
618
- * Warn when a Vue/Svelte island is present but its Astro integration isn't
619
- * installed — Vite would otherwise fail opaquely on the generated config import.
620
- * React ships with Blume, so it never needs this.
621
- */
622
- const islandFrameworkWarnings = (
623
- frameworks: Set<string>,
624
- root: string
625
- ): string[] => {
626
- const warnings: string[] = [];
627
- for (const framework of frameworks) {
628
- const dep = ISLAND_FRAMEWORK_DEPS.get(framework);
629
- if (dep && !canResolveFrom(root, dep)) {
630
- warnings.push(
631
- `Islands use ${framework}, which needs "${dep}". Install it (e.g. \`npm install ${dep} ${framework}\`).`
632
- );
633
- }
634
- }
635
- return warnings;
636
- };
637
-
638
- /**
639
- * Warn when the resolved server-output adapter is one the project must install
640
- * itself (Netlify/Cloudflare; Node and Vercel ship with Blume). The generated
641
- * astro.config.mjs imports the adapter package directly — and on those
642
- * platforms the adapter is even auto-selected from env vars — so warn early
643
- * rather than let the build die with an opaque ERR_MODULE_NOT_FOUND from the
644
- * hidden generated config. Availability mirrors the search-provider check: a
645
- * dep resolves from the project root or from the Blume package itself.
646
- * `pkgDir` is injectable for testing.
647
- */
648
- export const deploymentAdapterWarnings = (
649
- deployment: ResolvedConfig["deployment"],
650
- root: string,
651
- pkgDir: string = packageRoot()
652
- ): string[] => {
653
- const dep =
654
- deployment.output === "server" && deployment.adapter
655
- ? DEPLOYMENT_ADAPTER_DEPS.get(deployment.adapter)
656
- : undefined;
657
- if (dep && !(canResolveFrom(root, dep) || canResolveFrom(pkgDir, dep))) {
658
- return [
659
- `Deployment adapter "${deployment.adapter}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`,
660
- ];
661
- }
662
- return [];
663
- };
664
-
665
- /**
666
- * Warn when the configured search provider's SDK is missing. Provider SDKs are
667
- * optional peers; warn (rather than fail opaquely in Vite) when the package
668
- * isn't installed. A dep is available if the project installed it (resolves
669
- * from the root) OR Blume ships it (resolves from the Blume package — the same
670
- * set the `.blume` deps link exposes to the build). Resolving from the project
671
- * root alone falsely flagged a shipped SDK like Orama (the default provider)
672
- * as missing whenever it wasn't hoisted into the project, e.g. under isolated
673
- * linkers. We resolve from each package's real location rather than through
674
- * the `.blume` junction, which can't be traversed reliably for store-symlinked
675
- * deps. `pkgDir` is injectable for testing.
676
- */
677
- export const searchProviderWarnings = (
678
- provider: ResolvedConfig["search"]["provider"],
679
- root: string,
680
- pkgDir: string = packageRoot()
681
- ): string[] => {
682
- const warnings: string[] = [];
683
- for (const dep of searchProviderMeta(provider).runtimeDeps) {
684
- if (!(canResolveFrom(root, dep) || canResolveFrom(pkgDir, dep))) {
685
- warnings.push(
686
- `Search provider "${provider}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`
687
- );
688
- }
689
- }
690
- return warnings;
691
- };
692
-
693
- /**
694
- * Warn when the Ask AI backend's provider SDK is missing. Like search provider
695
- * SDKs, these are optional peers the project must install (only `gateway`
696
- * needs nothing beyond the core `ai` package Blume ships) — warn early with
697
- * the package name rather than let Vite fail to resolve the import opaquely.
698
- * Same resolution rule as {@link searchProviderWarnings}: available if the
699
- * project installed it or Blume can resolve it. `pkgDir` is injectable for
700
- * testing.
701
- */
702
- export const askProviderWarnings = (
703
- ask: ResolvedConfig["ai"]["ask"],
704
- root: string,
705
- pkgDir: string = packageRoot()
706
- ): string[] => {
707
- // An external `endpoint` means no generated route, so no SDK is imported.
708
- if (!ask?.enabled || ask.endpoint) {
709
- return [];
710
- }
711
- const dep = askBackendRuntimeDep(ask);
712
- if (!dep || canResolveFrom(root, dep) || canResolveFrom(pkgDir, dep)) {
713
- return [];
714
- }
715
- return [
716
- `Ask AI provider "${ask.provider}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`,
717
- ];
718
- };
719
-
720
490
  /** Absolute path to the configured `examples.css`, or null when unset. */
721
491
  const examplesCssFile = (
722
492
  root: string,
@@ -866,7 +636,7 @@ const writeIfChanged = async (
866
636
 
867
637
  /**
868
638
  * Delete generated files under `srcDir` that this pass didn't (re)write. The
869
- * generator emits many files conditionally — an Ask AI endpoint, OG images, a
639
+ * generator emits many files conditionally — an assistant endpoint, OG images, a
870
640
  * search index, RSS feeds, reference pages, the MCP server — so toggling a
871
641
  * feature off would otherwise leave a stale file behind, and a leftover
872
642
  * server-rendered endpoint breaks the static build. `writeIfChanged` only ever
@@ -908,7 +678,7 @@ export const collectStaged = (project: BlumeProject): Map<string, string> => {
908
678
  // agent-facing Markdown gets.
909
679
  const text = page.sourcePath
910
680
  ? rewriteRelativeImages({
911
- deployBase: project.config.deployment.base,
681
+ deployBase: project.config.deployment.options.base,
912
682
  projectRoot: project.context.root,
913
683
  source: page.body.text,
914
684
  sourcePath: page.sourcePath,
@@ -1225,9 +995,9 @@ const resolveOgSite = (config: ResolvedConfig): string | undefined => {
1225
995
  if (configured !== undefined) {
1226
996
  return configured;
1227
997
  }
1228
- return config.deployment.site
1229
- ? `${new URL(config.deployment.site).host}${normalizeBasePath(
1230
- config.deployment.base
998
+ return config.deployment.options.site
999
+ ? `${new URL(config.deployment.options.site).host}${normalizeBasePath(
1000
+ config.deployment.options.base
1231
1001
  )}`
1232
1002
  : undefined;
1233
1003
  };
@@ -1342,27 +1112,27 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1342
1112
 
1343
1113
  const data: BlumeData = {
1344
1114
  config: {
1345
- analytics: config.analytics ?? null,
1115
+ analytics: config.analytics,
1346
1116
  appleIcon: resolveAppleIcon(project),
1347
- ask: config.ai.ask?.enabled
1117
+ assistant: config.ai.assistant?.enabled
1348
1118
  ? {
1349
- endpoint: config.ai.ask.endpoint ?? null,
1350
- suggestions: config.ai.ask.suggestions,
1119
+ endpoint: config.ai.assistant.endpoint ?? null,
1120
+ suggestions: config.ai.assistant.suggestions,
1351
1121
  }
1352
1122
  : null,
1353
1123
  banner: resolveBanner(config),
1354
1124
  basePath: config.basePath,
1355
- codeThemes: config.markdown.codeBlocks.theme,
1125
+ codeThemes: config.markdown.code.theme,
1356
1126
  codeWrap: config.markdown.code.wrap,
1357
1127
  dateFormat: config.dateFormat,
1358
1128
  description: config.description,
1359
1129
  discovery: {
1360
- agentReadability: config.seo.agentReadability,
1130
+ agentReadability: config.agents.agentReadability,
1361
1131
  aiCatalog: hasAiCatalog(config),
1362
- api: config.ai.api,
1363
- llmsTxt: config.ai.llmsTxt.enabled,
1132
+ api: config.agents.api,
1133
+ llmsTxt: config.agents.llmsTxt.enabled,
1364
1134
  // Mirrors `buildSitemapFiles`: no site, no sitemap.
1365
- sitemap: config.seo.sitemap && Boolean(config.deployment.site),
1135
+ sitemap: config.seo.sitemap && Boolean(config.deployment.options.site),
1366
1136
  },
1367
1137
  favicon: resolveFavicon(project),
1368
1138
  feedback: config.feedback,
@@ -1392,10 +1162,10 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1392
1162
  : null,
1393
1163
  imageZoom: config.markdown.imageZoom,
1394
1164
  logo,
1395
- mcp: config.ai.mcp.enabled
1165
+ mcp: config.agents.mcp.enabled
1396
1166
  ? {
1397
- name: config.ai.mcp.name ?? config.title,
1398
- route: config.ai.mcp.route,
1167
+ name: config.agents.mcp.name ?? config.title,
1168
+ route: config.agents.mcp.route,
1399
1169
  }
1400
1170
  : null,
1401
1171
  // `og.enabled` is resolved to a definite boolean in `loadConfig`; coerce
@@ -1413,19 +1183,19 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1413
1183
  openInChat: config.ai.openInChat,
1414
1184
  repoUrl,
1415
1185
  search: {
1416
- enabled: config.search.provider !== "none",
1186
+ enabled: config.search.provider.mode !== "none",
1417
1187
  popular: resolveSearchPopular(config.search.popular, config.basePath),
1418
- provider: config.search.provider,
1188
+ provider: config.search.provider.kind,
1419
1189
  },
1420
- site: config.deployment.site ?? null,
1190
+ site: config.deployment.options.site ?? null,
1421
1191
  structuredData: config.seo.structuredData,
1422
1192
  theme: config.theme,
1423
1193
  title: config.title,
1424
1194
  toc: config.toc,
1425
1195
  versions: config.versions ?? null,
1426
1196
  webmcp: {
1427
- enabled: config.ai.webmcp,
1428
- llms: config.ai.llmsTxt.enabled,
1197
+ enabled: config.agents.webmcp,
1198
+ llms: config.agents.llmsTxt.enabled,
1429
1199
  },
1430
1200
  x: config.seo.x,
1431
1201
  },
@@ -1469,6 +1239,7 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1469
1239
  indexable: route.indexable,
1470
1240
  lastModified: route.lastModified ?? null,
1471
1241
  locale: route.locale,
1242
+ monolingual: route.monolingual ?? false,
1472
1243
  path: route.path,
1473
1244
  title: route.title,
1474
1245
  version: route.version,
@@ -1505,7 +1276,7 @@ const planMcp = (
1505
1276
  userPages: { pattern: string }[]
1506
1277
  ): McpPlan => {
1507
1278
  const { config } = project;
1508
- const { route } = config.ai.mcp;
1279
+ const { route } = config.agents.mcp;
1509
1280
  const dir = join(srcDir, "blume-mcp");
1510
1281
  const base: McpPlan = {
1511
1282
  dir,
@@ -1515,14 +1286,14 @@ const planMcp = (
1515
1286
  srcDir,
1516
1287
  warnings: [],
1517
1288
  };
1518
- if (!config.ai.mcp.enabled) {
1289
+ if (!config.agents.mcp.enabled) {
1519
1290
  return base;
1520
1291
  }
1521
1292
  if (routeIsTaken(userPages, project.graph.pages, route)) {
1522
1293
  return {
1523
1294
  ...base,
1524
1295
  warnings: [
1525
- `MCP server route "${route}" is already used by a content or custom page; the MCP server was not generated. Set a different "ai.mcp.route" in blume.config.ts.`,
1296
+ `MCP server route "${route}" is already used by a content or custom page; the MCP server was not generated. Set a different "agents.mcp.route" in blume.config.ts.`,
1526
1297
  ],
1527
1298
  };
1528
1299
  }
@@ -1640,13 +1411,13 @@ const planApi = (
1640
1411
  userPages: { pattern: string }[]
1641
1412
  ): ApiPlan => {
1642
1413
  const { config, context } = project;
1643
- const server = config.deployment.output === "server";
1414
+ const server = config.deployment.options.output === "server";
1644
1415
  return {
1645
1416
  catchAll:
1646
1417
  server &&
1647
1418
  !userPages.some(ownsApiRest) &&
1648
1419
  !project.graph.pages.some(contentUnderApi),
1649
- enabled: config.ai.api,
1420
+ enabled: config.agents.api,
1650
1421
  server,
1651
1422
  spec:
1652
1423
  !routeIsTaken(userPages, project.graph.pages, OPENAPI_PATH) &&
@@ -1701,10 +1472,10 @@ const writeApiFiles = async (
1701
1472
  join(plan.srcDir, "pages", "openapi.json.ts"),
1702
1473
  staticJsonEndpointTemplate(
1703
1474
  buildApiSpec({
1704
- agentReadability: config.seo.agentReadability,
1475
+ agentReadability: config.agents.agentReadability,
1705
1476
  base: data.base,
1706
1477
  description: config.description,
1707
- llmsTxt: config.ai.llmsTxt.enabled,
1478
+ llmsTxt: config.agents.llmsTxt.enabled,
1708
1479
  mcpRoute,
1709
1480
  name: config.title,
1710
1481
  search: plan.server,
@@ -1791,15 +1562,17 @@ const proxyAllowlistWarnings = (
1791
1562
  config: ResolvedConfig,
1792
1563
  data: OpenApiData
1793
1564
  ): string[] => {
1794
- const kinds = builtinProxyKinds(config);
1565
+ const proxied = new Set(
1566
+ builtinProxyReferences(config).map((reference) => reference.slug)
1567
+ );
1795
1568
  const warnings: string[] = [];
1796
1569
  for (const spec of Object.values(data)) {
1797
- if (!kinds.includes(spec.kind) || specOriginsOf(spec).length > 0) {
1570
+ if (!proxied.has(spec.slug) || specOriginsOf(spec).length > 0) {
1798
1571
  continue;
1799
1572
  }
1800
1573
  warnings.push(
1801
1574
  spec.kind === "graphql"
1802
- ? `The "${spec.label}" GraphQL reference (${spec.route}) has playground.proxy: true, but no absolute endpoint is configured for it, so the built-in proxy has no origin to allow and will refuse every request its playground sends. Set the graphql block's (or the source's) \`endpoint\` to the live GraphQL URL, or point playground.proxy at an external proxy URL.`
1575
+ ? `The "${spec.label}" GraphQL reference (${spec.route}) has playground.proxy: true, but no absolute endpoint is configured for it, so the built-in proxy has no origin to allow and will refuse every request its playground sends. Set \`endpoint\` on the graphql() adapter (or the source) to the live GraphQL URL, or point playground.proxy at an external proxy URL.`
1803
1576
  : `The "${spec.label}" reference (${spec.route}) has playground.proxy: true, but its spec declares no absolute servers[].url (relative and templated URLs carry no origin), so the built-in proxy has no origin to allow and will refuse every request its playground sends. Add an absolute server URL to the spec, or point playground.proxy at an external proxy URL.`
1804
1577
  );
1805
1578
  }
@@ -1807,9 +1580,9 @@ const proxyAllowlistWarnings = (
1807
1580
  };
1808
1581
 
1809
1582
  /**
1810
- * Write the Ask AI endpoint and, unless the backend runs its own retrieval
1583
+ * Write the assistant endpoint and, unless the backend runs its own retrieval
1811
1584
  * (Inkeep), the grounding snapshot the endpoint queries at request time. A no-op
1812
- * when Ask AI is disabled.
1585
+ * when the assistant is disabled.
1813
1586
  */
1814
1587
  const writeAskFiles = async (
1815
1588
  project: BlumeProject,
@@ -1817,21 +1590,20 @@ const writeAskFiles = async (
1817
1590
  write: (path: string, content: string) => Promise<boolean>,
1818
1591
  modules: RuntimeModules
1819
1592
  ): Promise<void> => {
1820
- const { ask } = project.config.ai;
1821
- if (!(ask?.enabled && !ask.endpoint)) {
1593
+ const { assistant } = project.config.ai;
1594
+ if (!(assistant?.enabled && !assistant.endpoint)) {
1822
1595
  return;
1823
1596
  }
1824
- const grounded = ask.provider !== "inkeep";
1825
- if (grounded) {
1597
+ const backend = resolveAskBackend(assistant.provider);
1598
+ if (backend.grounded) {
1826
1599
  modules.set("blume:ask-data", JSON.stringify(await buildAskData(project)));
1827
1600
  }
1828
1601
  await write(
1829
1602
  join(srcDir, "pages", "api", "ask.ts"),
1830
- askEndpointTemplate(resolveAskBackend(ask), grounded, {
1831
- cors: ask.cors,
1832
- instructions: ask.instructions,
1833
- reasoning: ask.reasoning,
1834
- retrieval: ask.retrieval,
1603
+ askEndpointTemplate(backend, {
1604
+ cors: assistant.cors,
1605
+ instructions: assistant.instructions,
1606
+ retrieval: assistant.retrieval,
1835
1607
  })
1836
1608
  );
1837
1609
  };
@@ -1871,6 +1643,36 @@ export const diagnosticWarning = (diagnostic: Diagnostic): string =>
1871
1643
  ? `${diagnostic.message} ${diagnostic.suggestion}`
1872
1644
  : diagnostic.message;
1873
1645
 
1646
+ /**
1647
+ * Missing-dependency preflight: the search provider's SDK, content source
1648
+ * SDKs, the assistant backend's provider SDK, the deployment adapter's package,
1649
+ * and — since React ships with Blume while Vue/Svelte don't — any island
1650
+ * framework's Astro integration. A build fails here, before anything is
1651
+ * written, with the install command for the project's package manager —
1652
+ * otherwise Vite dies later on an opaque unresolved import from the hidden
1653
+ * runtime. Dev warns and keeps serving: only the pages and routes that import
1654
+ * the package break, and installing it is picked up on the next restart.
1655
+ */
1656
+ const dependencyPreflight = async (
1657
+ project: BlumeProject,
1658
+ frameworks: Set<string>
1659
+ ): Promise<string[]> => {
1660
+ const build = project.mode === "build";
1661
+ const diagnostic = await missingDependencyDiagnostic(
1662
+ project.config,
1663
+ project.context.root,
1664
+ build ? "error" : "warning",
1665
+ frameworks
1666
+ );
1667
+ if (!diagnostic) {
1668
+ return [];
1669
+ }
1670
+ if (build) {
1671
+ throw new BlumeError(diagnostic);
1672
+ }
1673
+ return [diagnosticWarning(diagnostic)];
1674
+ };
1675
+
1874
1676
  export interface GenerateResult {
1875
1677
  /** Whether any structural file changed (config/page/content config). */
1876
1678
  structuralChange: boolean;
@@ -1879,33 +1681,19 @@ export interface GenerateResult {
1879
1681
  }
1880
1682
 
1881
1683
  /**
1882
- * Statically analyze the user's `components.ts` (never executing it) and plan the
1883
- * generated `components.ts` module plus any hydration wrappers. Returns the plan
1884
- * and the analyzer's warnings; a project with no components file gets an empty
1885
- * plan and no warnings.
1684
+ * Statically analyze the user's `components.ts` (never executing it). Empty for
1685
+ * a project with no components file; throws `BLUME_COMPONENTS_INVALID` for an
1686
+ * override that isn't one of the accepted static forms.
1886
1687
  */
1887
- const buildComponentSlots = async (
1688
+ export const analyzeComponentsFile = async (
1888
1689
  componentsFile: string | null
1889
- ): Promise<{
1890
- plan: ComponentSlotPlan;
1891
- /** MDX tags the overrides define (for the unknown-component check). */
1892
- tags: string[];
1893
- warnings: string[];
1894
- }> => {
1895
- const analysis = componentsFile
1690
+ ): Promise<ComponentOverrideAnalysis> =>
1691
+ componentsFile
1896
1692
  ? analyzeComponentOverrides(
1897
1693
  await readFile(componentsFile, "utf-8"),
1898
1694
  componentsFile
1899
1695
  )
1900
- : null;
1901
- return {
1902
- plan: planComponentSlots(componentsFile, analysis),
1903
- tags: analysis
1904
- ? [...analysis.mdx, ...analysis.islands].map((entry) => entry.key)
1905
- : [],
1906
- warnings: analysis ? analysis.warnings : [],
1907
- };
1908
- };
1696
+ : emptyComponentOverrides();
1909
1697
 
1910
1698
  /** The OG endpoint fonts for a scanned project (see {@link resolveOgFonts}). */
1911
1699
  const projectOgFonts = (project: BlumeProject): DerivedOgFonts =>
@@ -2057,7 +1845,7 @@ export const generateRuntime = async (
2057
1845
  const homeLinkHeader =
2058
1846
  buildHomeLinkHeader(config, contentRoutes) ?? undefined;
2059
1847
 
2060
- const askEnabled = config.ai.ask?.enabled ?? false;
1848
+ const assistantEnabled = config.ai.assistant?.enabled ?? false;
2061
1849
  const exportPdf = config.export.pdf;
2062
1850
  const exportEpub = config.export.epub;
2063
1851
  // Every route's source Markdown: published as `blume:raw-markdown` below,
@@ -2072,10 +1860,10 @@ export const generateRuntime = async (
2072
1860
  // entryId so i18n duplicates of one entry write a single file. Collected here
2073
1861
  // so math detection also sees staged bodies (they never live under root).
2074
1862
  const staged = collectStaged(project);
2075
- // Statically analyze `components.ts` overrides (never executed): drives the
2076
- // `islands` group, hydration on layout/mdx overrides, string-path resolution,
2077
- // and the "framework component with no client mode" diagnostic. Independent of
2078
- // the discovery reads, so it joins the same parallel batch.
1863
+ // Statically analyze `components.ts` overrides (never executed): drives
1864
+ // hydration on layout/mdx overrides, string-path resolution, and the
1865
+ // "framework component with no client mode" diagnostic. Independent of the
1866
+ // discovery reads, so it joins the same parallel batch.
2079
1867
  const [
2080
1868
  pages,
2081
1869
  detectedReact,
@@ -2085,7 +1873,7 @@ export const generateRuntime = async (
2085
1873
  integrationBridge,
2086
1874
  islandDiscovery,
2087
1875
  exampleDiscovery,
2088
- componentSlots,
1876
+ overrideAnalysis,
2089
1877
  ] = await Promise.all([
2090
1878
  context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
2091
1879
  detectNeedsReact(context.root),
@@ -2095,19 +1883,21 @@ export const generateRuntime = async (
2095
1883
  loadIntegrationBridge(config, context),
2096
1884
  discoverIslands(context.root),
2097
1885
  discoverExamples(context.root, config.examples.source),
2098
- buildComponentSlots(context.componentsFile),
1886
+ analyzeComponentsFile(context.componentsFile),
2099
1887
  ]);
2100
- const {
2101
- plan: slotPlan,
2102
- tags: overrideTags,
2103
- warnings: overrideWarnings,
2104
- } = componentSlots;
1888
+ // The `islands/` convention and `components.ts` share one static plan: every
1889
+ // entry is imported by path, hydrated ones through a generated wrapper.
1890
+ const slotPlan = planComponentSlots(
1891
+ islandDiscovery.islands,
1892
+ overrideAnalysis
1893
+ );
1894
+ const overrideWarnings = overrideAnalysis.warnings;
2105
1895
  // Expose the discovered examples for agent-facing Markdown downleveling
2106
1896
  // (`<Component>` → source) before any consumer (raw `.md`, MCP, llms) runs.
2107
1897
  project.examples = exampleMarkdownLookup(exampleDiscovery.examples);
2108
1898
 
2109
1899
  // Each island/example framework enables its Astro renderer. React also
2110
- // switches on for any project `.tsx`/`.jsx` and for Ask AI; Vue/Svelte are
1900
+ // switches on for any project `.tsx`/`.jsx` and for the assistant; Vue/Svelte are
2111
1901
  // island/example-driven. `.astro` examples need no renderer. Component
2112
1902
  // overrides referencing a framework component enable its renderer too.
2113
1903
  const frameworks = new Set<string>([
@@ -2115,7 +1905,9 @@ export const generateRuntime = async (
2115
1905
  ...exampleDiscovery.examples.map((example) => example.framework),
2116
1906
  ...slotPlan.frameworks,
2117
1907
  ]);
2118
- const needsReact = detectedReact || askEnabled || frameworks.has("react");
1908
+ const dependencyWarnings = await dependencyPreflight(project, frameworks);
1909
+ const needsReact =
1910
+ detectedReact || assistantEnabled || frameworks.has("react");
2119
1911
  const needsVue = frameworks.has("vue");
2120
1912
  const needsSvelte = frameworks.has("svelte");
2121
1913
 
@@ -2172,7 +1964,7 @@ export const generateRuntime = async (
2172
1964
  // sources, so the `docs` glob would otherwise scan (and watch) the whole
2173
1965
  // project root for nothing — see contentConfigTemplate.
2174
1966
  const hasFilesystemSource = project.sources.some((source) => !source.staged);
2175
- const docsCollection = resolveDocsCollection(config, context);
1967
+ const docsCollection = resolveDocsCollection(config, context.root);
2176
1968
 
2177
1969
  // All of these write to distinct generated paths and never read one another's
2178
1970
  // output, so the structural files, the per-convention hydration wrappers, and
@@ -2234,12 +2026,8 @@ export const generateRuntime = async (
2234
2026
  // The header's Ask trigger, behind the `blume:ask` alias. Always written
2235
2027
  // (even when Ask is off, as a component that renders nothing) so the alias
2236
2028
  // resolves — the same contract as `blume:search-client`.
2237
- write(askPath, askComponentTemplate(askEnabled)),
2029
+ write(askPath, askComponentTemplate(assistantEnabled)),
2238
2030
  write(join(srcDir, "generated", "components.ts"), slotPlan.module),
2239
- write(
2240
- join(srcDir, "generated", "islands.ts"),
2241
- islandMapTemplate(islandDiscovery.islands)
2242
- ),
2243
2031
  write(
2244
2032
  join(srcDir, "generated", "examples.ts"),
2245
2033
  exampleMapTemplate(exampleDiscovery.examples, config.basePath)
@@ -2272,18 +2060,7 @@ export const generateRuntime = async (
2272
2060
  })
2273
2061
  ),
2274
2062
  ]),
2275
- // Per-island hydration wrappers for the `islands/` convention. The map
2276
- // module (written above, always) imports these; orphans from removed
2277
- // islands are pruned at the end of the pass.
2278
- Promise.all(
2279
- islandDiscovery.islands.map((island) =>
2280
- write(
2281
- join(srcDir, "generated", "islands", `${island.name}.astro`),
2282
- islandWrapperTemplate(island)
2283
- )
2284
- )
2285
- ),
2286
- // Per-override hydration wrappers for `defineComponents` islands and
2063
+ // Per-override hydration wrappers for `islands/` convention components and
2287
2064
  // `client:*` layout/mdx overrides. The generated `components.ts` (written
2288
2065
  // above) imports these; orphans from removed overrides are pruned at the
2289
2066
  // end of the pass.
@@ -2336,14 +2113,13 @@ export const generateRuntime = async (
2336
2113
  );
2337
2114
  }
2338
2115
 
2339
- // Changelog index (`/changelog`), rendered through the Update timeline layout.
2116
+ // Changelog index (`/changelog`): every release as a row, grouped by year.
2340
2117
  if (changelogIndex) {
2341
2118
  await write(
2342
2119
  join(srcDir, "pages", "changelog.astro"),
2343
2120
  changelogIndexTemplate({
2344
2121
  exportEpub,
2345
2122
  exportPdf,
2346
- mathEnabled: usesMath,
2347
2123
  needsReact,
2348
2124
  staged: hasStaged,
2349
2125
  })
@@ -2369,8 +2145,9 @@ export const generateRuntime = async (
2369
2145
  write(featuresPath, featuresTemplate(clientFeatures)),
2370
2146
  ]);
2371
2147
 
2372
- // Client-loaded providers (orama, flexsearch) ship a static index + endpoint.
2373
- if (servesStaticIndex(config.search.provider)) {
2148
+ // Client-loaded adapters (orama, flexsearch) ship a static index + endpoint.
2149
+ const searchAdapter = config.search.provider;
2150
+ if (searchAdapter.mode === "static") {
2374
2151
  const documents = await buildSearchDocuments(project);
2375
2152
  modules.set("blume:search-index", JSON.stringify(documents));
2376
2153
  await write(
@@ -2380,10 +2157,10 @@ export const generateRuntime = async (
2380
2157
  }
2381
2158
 
2382
2159
  // Mixedbread proxies queries through a server endpoint that holds the key.
2383
- if (config.search.provider === "mixedbread") {
2160
+ if (searchAdapter.kind === "mixedbread") {
2384
2161
  await write(
2385
2162
  join(srcDir, "pages", "api", "search.ts"),
2386
- mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? "")
2163
+ mixedbreadSearchEndpointTemplate(searchAdapter.options)
2387
2164
  );
2388
2165
  }
2389
2166
 
@@ -2432,9 +2209,8 @@ export const generateRuntime = async (
2432
2209
  );
2433
2210
  }
2434
2211
 
2435
- // Scalar-rendered API/AsyncAPI reference pages (`renderer: "scalar"`). One
2436
- // self-contained page per source, mounted on its configured route and
2437
- // regenerated each run.
2212
+ // `scalar()` reference pages. One self-contained page per source, mounted
2213
+ // on its configured route and regenerated each run.
2438
2214
  const warnings: string[] = [
2439
2215
  ...(depsLinkWarning ? [depsLinkWarning] : []),
2440
2216
  ...proxyAllowlistWarnings(config, openApiData),
@@ -2472,23 +2248,15 @@ export const generateRuntime = async (
2472
2248
  // or a `components.ts` override. Needs the project's own components, known here.
2473
2249
  const knownComponentTags = new Set<string>([
2474
2250
  ...islandDiscovery.islands.map((island) => island.name),
2475
- ...overrideTags,
2251
+ ...overrideAnalysis.mdx.map((entry) => entry.key),
2476
2252
  ]);
2477
- // Missing-dependency preflights: the search provider's SDK, the Ask AI
2478
- // backend's provider SDK, the deployment adapter's package, and — since
2479
- // React ships with Blume while Vue/Svelte don't — any island framework's
2480
- // Astro integration. Warn early rather than let Vite fail to resolve them
2481
- // opaquely.
2482
2253
  warnings.push(
2483
2254
  ...validateUsedComponents(
2484
2255
  project.graph.pages,
2485
2256
  knownComponentTags,
2486
2257
  new Set(registry.map((item) => item.name))
2487
2258
  ).map(diagnosticWarning),
2488
- ...searchProviderWarnings(config.search.provider, context.root),
2489
- ...askProviderWarnings(config.ai.ask, context.root),
2490
- ...deploymentAdapterWarnings(config.deployment, context.root),
2491
- ...islandFrameworkWarnings(frameworks, context.root)
2259
+ ...dependencyWarnings
2492
2260
  );
2493
2261
  if (hasScalarReferences(config)) {
2494
2262
  const references = await buildReferenceFiles({
@@ -2521,7 +2289,7 @@ export const generateRuntime = async (
2521
2289
  writeStagedContent(out, staged),
2522
2290
  ]);
2523
2291
 
2524
- // Remove anything under `.blume/src` this pass didn't write — e.g. an Ask AI
2292
+ // Remove anything under `.blume/src` this pass didn't write — e.g. an assistant
2525
2293
  // endpoint left behind after the feature was switched off.
2526
2294
  await pruneOrphans(srcDir, written);
2527
2295