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