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
@@ -4,7 +4,11 @@ import { z } from "zod";
4
4
 
5
5
  import type { BlumeConfig } from "./config-input.ts";
6
6
  import { applyDeploymentEnv } from "./deployment-env.ts";
7
- import { BlumeError, diagnosticsFromZod } from "./diagnostics.ts";
7
+ import {
8
+ BlumeError,
9
+ diagnosticsFromIssues,
10
+ diagnosticsFromZod,
11
+ } from "./diagnostics.ts";
8
12
  import { createModuleLoader } from "./load-module.ts";
9
13
  import { findConfigFile } from "./project.ts";
10
14
  import { blumeConfigSchema } from "./schema.ts";
@@ -45,10 +49,12 @@ import type { Diagnostic } from "./types.ts";
45
49
  * dismissible }`.
46
50
  *
47
51
  * **Content & navigation**
48
- * - `content` — where content lives (`root`, defaults to `docs`) and pluggable
49
- * `sources` (filesystem, remote MDX, GitHub Releases, Sanity, Notion, or a
50
- * custom `ContentSource`). Omit `sources` and the top-level `root` becomes one
51
- * implicit filesystem source.
52
+ * - `content` — where content lives: adapters from `blume/sources` under
53
+ * `sources` (`filesystem({ root })`, `mdxRemote({…})`, `githubReleases({…})`,
54
+ * `sanity({…})`, `notion({…})`, `contentful({…})`, `payload({…})`,
55
+ * `strapi({…})`, `obsidian({…})`, or `custom(source)`), or the
56
+ * zero-config shorthand `root`/`include`/`exclude`, which desugars to one
57
+ * `filesystem()` source and can't be combined with `sources`.
52
58
  * - `navigation` — sidebar, header `tabs`, `selectors` (version/language/product
53
59
  * switchers), pinned `featured` links, header `actions` and the one `cta`,
54
60
  * and the `repo` link (a toggle, or a URL). Omit `sidebar` to generate it
@@ -70,35 +76,41 @@ import type { Diagnostic } from "./types.ts";
70
76
  * - `export` — reader-facing PDF/EPUB export actions (off by default).
71
77
  *
72
78
  * **Reference docs**
73
- * - `openapi` — native OpenAPI reference: one real page per operation, woven
74
- * into the sidebar and search. Point `sources`/`spec` at your spec.
75
- * - `asyncapi` — native AsyncAPI reference with the same treatment; 2.x specs
76
- * are normalized to 3.x automatically.
79
+ * - `reference` — API references as a list of adapters from
80
+ * `blume/reference`: `openapi({…})` and `asyncapi({…})` render native pages
81
+ * (one real page per operation, woven into the sidebar and search; AsyncAPI
82
+ * 2.x specs are normalized to 3.x), `graphql({…})` renders a schema, and
83
+ * `scalar({…})` embeds the Scalar reference instead.
77
84
  *
78
- * **Search & AI**
79
- * - `search` — search backend `provider` (`orama` by default; `pagefind`,
80
- * `algolia`, `typesense`, `orama-cloud`, `mixedbread`, or `none`) plus its
81
- * credential block.
82
- * - `ai` — `ask` (the Ask AI chat endpoint and its provider/model), `llmsTxt`
83
- * (emit `llms.txt`), `mcp` (expose the docs as an MCP server for connecting
84
- * agents), and `markdownComponents` (Markdown serializers for custom
85
- * components in agent-facing output).
85
+ * **Search, AI & agents**
86
+ * - `search` — a search adapter from `blume/search` (`orama()` by default;
87
+ * `flexsearch()`, `pagefind()`, `algolia({…})`, `oramaCloud({…})`,
88
+ * `typesense({…})`, `mixedbread({…})`, or `false`), or `{ provider,
89
+ * popular, indexing }` to add curated links and indexing settings.
90
+ * - `ai` — what faces a model at read time: `assistant` (the chat assistant, with
91
+ * a provider adapter from `blume/ai` such as `gateway()` or `openrouter()`)
92
+ * and `openInChat` (the "Open in chat" page action).
93
+ * - `agents` — the machine-readable surface: `llmsTxt`, the JSON `api`, the
94
+ * `mcp` server, published `skills`, `markdownComponents` (Markdown
95
+ * serializers for custom components), the `catalog` manifests,
96
+ * `agentReadability`, robots `contentSignals`, `webmcp`, and `webBotAuth`.
86
97
  *
87
98
  * **SEO, feeds & analytics**
88
- * - `seo` — `og` images, `sitemap`, `robots`, `rss` feeds, `structuredData`
89
- * JSON-LD, `agentReadability`, and robots `contentSignals`.
90
- * - `analytics` — PostHog, Vercel, or arbitrary `scripts` (Plausible, Fathom,
91
- * GA, …).
99
+ * - `seo` — `og` images, `sitemap`, `robots`, `rss` feeds, and
100
+ * `structuredData` JSON-LD.
101
+ * - `analytics` — a list of adapters from `blume/analytics`, one per provider
102
+ * (`posthog()`, `googleAnalytics()`, `plausible()`, `fathom()`, `vercel()`,
103
+ * `cloudflare()`, …), or `script()` for anything without one.
92
104
  *
93
105
  * **Astro**
94
106
  * - `integrations` — Astro integrations appended after Blume's built-ins, in
95
107
  * declaration order. Install and maintain each integration in the site.
96
108
  *
97
109
  * **Deployment & i18n**
98
- * - `deployment` — `site` URL (needed for absolute links, sitemaps, and OG),
99
- * `adapter` (`vercel`/`node`/`netlify`/`cloudflare`), `output`
100
- * (`static`/`server`), and `base` path. Auto-detected on Vercel/Netlify/
101
- * Cloudflare from the platform env.
110
+ * - `deployment` — a host adapter from `blume/deploy` (`vercel()`, `node()`,
111
+ * `netlify()`, `cloudflare()`) for a server build, each taking `site`,
112
+ * `base`, and `output`; or `{ site, base }` for a static build anywhere.
113
+ * `site` is auto-detected on Vercel/Netlify/Cloudflare from the platform env.
102
114
  * - `i18n` — opt-in multi-locale: `locales`, `defaultLocale`, `parser`
103
115
  * (`dir` vs filename `dot` suffix), and per-locale UI overrides.
104
116
  *
@@ -113,33 +125,41 @@ import type { Diagnostic } from "./types.ts";
113
125
  *
114
126
  * @example A production docs site with theming, search, and deployment.
115
127
  * ```ts
128
+ * import { vercel } from "blume/deploy";
129
+ * import { orama } from "blume/search";
130
+ *
116
131
  * export default defineConfig({
117
132
  * title: "Acme Docs",
118
133
  * description: "Build faster with Acme.",
119
134
  * logo: { image: "/logo.svg", text: "Acme" },
120
135
  * github: { owner: "acme", repo: "acme" },
121
- * theme: { accent: "violet", fonts: { body: "inter" }, radius: "lg" },
136
+ * theme: { accent: "purple", fonts: { body: "inter" }, radius: "lg" },
122
137
  * navigation: {
123
138
  * tabs: [
124
139
  * { label: "Guides", path: "/guides" },
125
140
  * { label: "API", path: "/api" },
126
141
  * ],
127
142
  * },
128
- * search: { provider: "orama" },
129
- * deployment: { site: "https://docs.acme.com", adapter: "vercel" },
143
+ * search: orama(),
144
+ * // A server build on Vercel.
145
+ * deployment: vercel({ site: "https://docs.acme.com" }),
130
146
  * });
131
147
  * ```
132
148
  *
133
- * @example An OpenAPI reference with the Ask AI assistant enabled.
149
+ * @example An OpenAPI reference with the assistant enabled.
134
150
  * ```ts
151
+ * import { openapi } from "blume/reference";
152
+ *
135
153
  * export default defineConfig({
136
154
  * title: "Acme API",
137
- * openapi: {
138
- * enabled: true,
139
- * route: "/reference",
140
- * sources: [{ label: "Core", spec: "./openapi.json" }],
141
- * },
142
- * ai: { ask: { enabled: true }, llmsTxt: true },
155
+ * reference: [
156
+ * openapi({
157
+ * route: "/reference",
158
+ * sources: [{ label: "Core", spec: "./openapi.json" }],
159
+ * }),
160
+ * ],
161
+ * agents: { llmsTxt: true },
162
+ * ai: { assistant: { enabled: true } },
143
163
  * });
144
164
  * ```
145
165
  *
@@ -149,6 +169,21 @@ import type { Diagnostic } from "./types.ts";
149
169
  */
150
170
  export const defineConfig = (config: BlumeConfig): BlumeConfig => config;
151
171
 
172
+ /**
173
+ * A config that fails validation. `diagnostic` folds every issue into the one
174
+ * message a command prints; `issues` keeps each on its own, with its own
175
+ * line, for `blume upgrade`, which lists them one by one.
176
+ */
177
+ export class ConfigValidationError extends BlumeError {
178
+ readonly issues: Diagnostic[];
179
+
180
+ constructor(diagnostic: Diagnostic, issues: Diagnostic[]) {
181
+ super(diagnostic);
182
+ this.name = "ConfigValidationError";
183
+ this.issues = issues;
184
+ }
185
+ }
186
+
152
187
  /** Result of loading + validating a project config. */
153
188
  export interface ConfigLoadResult {
154
189
  config: ResolvedConfig;
@@ -169,12 +204,62 @@ const importConfigModule = createModuleLoader();
169
204
  /**
170
205
  * The slice of a user config module probed before schema defaults apply:
171
206
  * whether `theme.fonts` was actually set. `looseObject` keeps every other key
172
- * out of scope; a non-object at either level simply fails the probe.
207
+ * out of scope; a non-object at either level simply fails the probe. `fonts`
208
+ * is optional here — Zod 4 treats a bare `z.unknown()` key as required, which
209
+ * would fail the probe for every `theme` that doesn't set fonts.
173
210
  */
174
211
  const themeFontsProbeSchema = z.looseObject({
175
- theme: z.looseObject({ fonts: z.unknown() }).optional(),
212
+ theme: z.looseObject({ fonts: z.unknown().optional() }).optional(),
176
213
  });
177
214
 
215
+ const isPathSegment = (segment: PropertyKey): segment is string | number =>
216
+ typeof segment !== "symbol";
217
+
218
+ /**
219
+ * Where an issue is located in the config source: its own path, except that
220
+ * an unknown key — which Zod reports on its parent's path — is located at the
221
+ * key itself, so a removed field points at the line that sets it.
222
+ */
223
+ const locationPath = (issue: z.core.$ZodIssue): (string | number)[] => [
224
+ ...issue.path.filter(isPathSegment),
225
+ ...(issue.code === "unrecognized_keys" ? issue.keys.slice(0, 1) : []),
226
+ ];
227
+
228
+ /** Sort key for a config issue: the line that set the field, else last. */
229
+ const lineRank = (diagnostic: Diagnostic): number =>
230
+ diagnostic.line ?? Number.MAX_SAFE_INTEGER;
231
+
232
+ /**
233
+ * One diagnostic per config issue, each anchored to the config file and, when
234
+ * the source is on disk, to the line and column that set the field. Issues on
235
+ * the config's own top level (a removed top-level block) lead, since they name
236
+ * the biggest moves; the rest read top to bottom, in source order.
237
+ */
238
+ const configIssues = (
239
+ error: z.ZodError,
240
+ options: { file?: string; source?: string }
241
+ ): Diagnostic[] => {
242
+ const code = "BLUME_CONFIG_INVALID";
243
+ const located = diagnosticsFromIssues(
244
+ error.issues.map((issue) => ({
245
+ message: issue.message,
246
+ path: locationPath(issue),
247
+ })),
248
+ { code, source: options.source }
249
+ );
250
+ return diagnosticsFromZod(error, { code, ...options })
251
+ .map((diagnostic, index) => ({
252
+ ...diagnostic,
253
+ column: located[index]?.column,
254
+ line: located[index]?.line,
255
+ }))
256
+ .toSorted(
257
+ (a, b) =>
258
+ Number(Boolean(a.schemaPath)) - Number(Boolean(b.schemaPath)) ||
259
+ lineRank(a) - lineRank(b)
260
+ );
261
+ };
262
+
178
263
  /**
179
264
  * Load and validate the project config. When no config file exists, schema
180
265
  * defaults produce a fully resolved config so the zero-boilerplate path works.
@@ -219,8 +304,7 @@ export const loadConfig = async (
219
304
  configFile && existsSync(configFile)
220
305
  ? readFileSync(configFile, "utf-8")
221
306
  : undefined;
222
- const diagnostics = diagnosticsFromZod(parsed.error, {
223
- code: "BLUME_CONFIG_INVALID",
307
+ const diagnostics = configIssues(parsed.error, {
224
308
  file: configFile ?? undefined,
225
309
  source,
226
310
  });
@@ -241,14 +325,14 @@ export const loadConfig = async (
241
325
  message: `${primary.message}\n${rest.length} more config issue(s):\n${moreIssues}`,
242
326
  }
243
327
  : primary;
244
- throw new BlumeError(detail);
328
+ throw new ConfigValidationError(detail, diagnostics);
245
329
  }
246
330
 
247
331
  // Resolve the canonical site URL, then SEO defaults that depend on it.
248
332
  // Precedence: explicit config > platform env (Vercel/Netlify/Cloudflare, via
249
333
  // applyDeploymentEnv) > the local dev server URL (dev only).
250
334
  const config = applyDeploymentEnv(parsed.data);
251
- const site = config.deployment.site ?? options.devServerUrl;
335
+ const site = config.deployment.options.site ?? options.devServerUrl;
252
336
 
253
337
  // OG images need an absolute `og:image`, so they default on once a site URL
254
338
  // is known and off otherwise. An explicit `seo.og.enabled` always wins.
@@ -257,7 +341,12 @@ export const loadConfig = async (
257
341
  return {
258
342
  config: {
259
343
  ...config,
260
- deployment: { ...config.deployment, site },
344
+ deployment: site
345
+ ? {
346
+ ...config.deployment,
347
+ options: { ...config.deployment.options, site },
348
+ }
349
+ : config.deployment,
261
350
  seo: { ...config.seo, og: { ...config.seo.og, enabled: ogEnabled } },
262
351
  },
263
352
  configFile,
@@ -0,0 +1,105 @@
1
+ import { extname, relative } from "pathe";
2
+ import { glob, globSync } from "tinyglobby";
3
+
4
+ /**
5
+ * Custom `.astro` pages (the `pages/` folder): discovery and the routes they
6
+ * serve. Lives in core so the content graph can see them too — a header tab or
7
+ * brand link that points at a custom page must know the page exists only at
8
+ * its own path, not under every locale prefix.
9
+ */
10
+
11
+ /** A user `.astro` page and the route pattern Blume injects it at. */
12
+ export interface CustomPageRoute {
13
+ /** Route pattern, e.g. `/changelog` or `/examples/[slug]`. */
14
+ pattern: string;
15
+ /** Absolute path to the user's `.astro` page file. */
16
+ entrypoint: string;
17
+ }
18
+
19
+ const PAGE_GLOB = ["**/*.astro"];
20
+
21
+ /**
22
+ * Astro's routing convention: a file or folder whose name starts with `_` is a
23
+ * private partial — importable (shared layouts, home-page sections), but never
24
+ * built into a route. Blume injects pages itself, so it must reproduce the same
25
+ * exclusion or every `pages/_home/Hero.astro`-style component ships as an HTML
26
+ * page.
27
+ */
28
+ const isPrivatePage = (rel: string): boolean =>
29
+ rel.split("/").some((segment) => segment.startsWith("_"));
30
+
31
+ /** Map discovered page files to routes; shared by the async/sync discoverers. */
32
+ const toPageRoutes = (
33
+ pagesRoot: string,
34
+ files: string[]
35
+ ): CustomPageRoute[] => {
36
+ files.sort();
37
+ const routes: CustomPageRoute[] = [];
38
+ for (const file of files) {
39
+ const rel = relative(pagesRoot, file);
40
+ if (isPrivatePage(rel)) {
41
+ continue;
42
+ }
43
+ const withoutExt = rel.slice(0, rel.length - extname(rel).length);
44
+ const parts = withoutExt.split("/");
45
+ // Only a trailing `index` maps to its parent dir; a folder literally named
46
+ // `index` (e.g. `index/foo.astro`) must keep its segment.
47
+ if (parts.at(-1) === "index") {
48
+ parts.pop();
49
+ }
50
+ const pattern = parts.length === 0 ? "/" : `/${parts.join("/")}`;
51
+ routes.push({ entrypoint: file, pattern });
52
+ }
53
+ return routes;
54
+ };
55
+
56
+ /**
57
+ * Discover user `.astro` pages and map them to route patterns. Files keep their
58
+ * original location; only the route pattern is derived (index -> parent,
59
+ * dynamic `[param]` segments preserved).
60
+ */
61
+ export const discoverPages = async (
62
+ pagesRoot: string
63
+ ): Promise<CustomPageRoute[]> =>
64
+ toPageRoutes(
65
+ pagesRoot,
66
+ await glob(PAGE_GLOB, { absolute: true, cwd: pagesRoot, onlyFiles: true })
67
+ );
68
+
69
+ /** {@link discoverPages} for synchronous callers (e.g. the sitemap builder). */
70
+ export const discoverPagesSync = (pagesRoot: string): CustomPageRoute[] =>
71
+ toPageRoutes(
72
+ pagesRoot,
73
+ globSync(PAGE_GLOB, { absolute: true, cwd: pagesRoot, onlyFiles: true })
74
+ );
75
+
76
+ /** Skip private (`_partial`, `.well-known`) and Astro dynamic (`[param]`) parts. */
77
+ const PRIVATE_SEGMENT = /^[._]/u;
78
+
79
+ /** Segments of a static, shareable page pattern; null for dynamic/private ones. */
80
+ export const staticSegments = (pattern: string): string[] | null => {
81
+ const segments = pattern.split("/").filter(Boolean);
82
+ return segments.some(
83
+ (part) => PRIVATE_SEGMENT.test(part) || part.includes("[")
84
+ )
85
+ ? null
86
+ : segments;
87
+ };
88
+
89
+ /**
90
+ * The static routes served by custom `.astro` pages — the same filtering as
91
+ * the generated OG cards, but yielding the routes themselves. Feeds the route
92
+ * sets that must know every servable page beyond the content graph (the link
93
+ * checker, the sitemap); dynamic (`[param]`) and private segments are skipped
94
+ * because their concrete URLs can't be enumerated statically.
95
+ */
96
+ export const customStaticRoutes = (pages: { pattern: string }[]): string[] => {
97
+ const routes = new Set<string>();
98
+ for (const { pattern } of pages) {
99
+ const segments = staticSegments(pattern);
100
+ if (segments !== null) {
101
+ routes.add(segments.length === 0 ? "/" : `/${segments.join("/")}`);
102
+ }
103
+ }
104
+ return [...routes];
105
+ };
package/src/core/data.ts CHANGED
@@ -1,7 +1,8 @@
1
+ import type { SearchAdapterKind } from "../search/adapters/registry.ts";
1
2
  import type { StructuredDataIdentity } from "../seo/jsonld.ts";
2
3
  import type { FontHead } from "../theme/fonts.ts";
3
4
  import type { UIStrings } from "./i18n-ui.ts";
4
- import type { ResolvedConfig, SearchProvider } from "./schema.ts";
5
+ import type { ResolvedConfig } from "./schema.ts";
5
6
  import type { Navigation, RouteAlternate, VersionAlternate } from "./types.ts";
6
7
 
7
8
  /**
@@ -98,6 +99,11 @@ export interface BlumeRoute {
98
99
  lastModified: string | null;
99
100
  /** Resolved locale code (the default locale when not under i18n). */
100
101
  locale: string;
102
+ /**
103
+ * True when the page's source publishes one language only (GitHub
104
+ * Releases), so the page renders without a language switcher.
105
+ */
106
+ monolingual: boolean;
101
107
  path: string;
102
108
  title: string;
103
109
  /** Resolved docs version (`""` for the current docs). */
@@ -112,35 +118,37 @@ export interface BlumeRoute {
112
118
 
113
119
  /** Site-wide settings derived from `blume.config` — the `config` field of {@link BlumeData}. */
114
120
  export interface BlumeDataConfig {
115
- analytics: NonNullable<ResolvedConfig["analytics"]> | null;
121
+ /** Analytics adapter descriptors, in configured order; empty when none. */
122
+ analytics: ResolvedConfig["analytics"];
116
123
  /** Apple touch icon, or `null` when none is configured/detected. */
117
124
  appleIcon: BlumeFavicon | null;
118
- /** Ask AI empty-state suggestions, or `null` when Ask AI is off. */
119
- ask: {
125
+ /** The assistant's empty-state suggestions, or `null` when the assistant is off. */
126
+ assistant: {
120
127
  endpoint: string | null;
121
- suggestions: NonNullable<ResolvedConfig["ai"]["ask"]>["suggestions"];
128
+ suggestions: NonNullable<ResolvedConfig["ai"]["assistant"]>["suggestions"];
122
129
  } | null;
123
130
  banner: BlumeBanner | null;
124
131
  /** Site-wide route mount point, normalized to `""` or `/seg` (see config). */
125
132
  basePath: string;
126
- /** `markdown.codeBlocks.theme`: light/dark Shiki themes for code surfaces. */
127
- codeThemes: ResolvedConfig["markdown"]["codeBlocks"]["theme"];
133
+ /** `markdown.code.theme`: light/dark Shiki themes for code surfaces. */
134
+ codeThemes: ResolvedConfig["markdown"]["code"]["theme"];
128
135
  /** `markdown.code.wrap`: wrap long code lines instead of scrolling. */
129
136
  codeWrap: boolean;
130
137
  /** `dateFormat`: `Intl.DateTimeFormat` options for the date stamps. */
131
138
  dateFormat: ResolvedConfig["dateFormat"];
132
139
  description: string | undefined;
133
140
  /**
134
- * Which agent-discovery resources exist for the layout to advertise in every
135
- * page's `<head>` (`seo.agentReadability`, `ai.llmsTxt.enabled`) — the HTML
136
- * counterpart of the homepage-only HTTP `Link` header, for agents that enter
137
- * on a deep page (see `ai/link-headers.ts`). `sitemap` (`seo.sitemap` with a
141
+ * Which agent-discovery resources exist for every layout to advertise in its
142
+ * page's `<head>` (`agents.agentReadability`, `agents.llmsTxt.enabled`) via
143
+ * the shared `DiscoveryLinks.astro` partial — the HTML counterpart of the
144
+ * homepage-only HTTP `Link` header, for agents that enter on a deep page
145
+ * (see `ai/link-headers.ts`). `sitemap` (`seo.sitemap` with a
138
146
  * `deployment.site`, the condition under which one is emitted) feeds the
139
147
  * 404 page's recovery links rather than the head.
140
148
  */
141
149
  discovery: {
142
150
  agentReadability: boolean;
143
- /** Whether the AI Catalog / ARD manifest is published (`ai.catalog`). */
151
+ /** Whether the AI Catalog / ARD manifest is published (`agents.catalog`). */
144
152
  aiCatalog: boolean;
145
153
  /** Whether the JSON docs API and its `/openapi.json` are published. */
146
154
  api: boolean;
@@ -203,7 +211,8 @@ export interface BlumeDataConfig {
203
211
  enabled: boolean;
204
212
  /** Resolved empty-state links; empty when unset (Search falls back to sidebar). */
205
213
  popular: { icon?: string; label: string; route: string }[];
206
- provider: SearchProvider;
214
+ /** The configured adapter's kind (`none` when search is disabled). */
215
+ provider: SearchAdapterKind;
207
216
  };
208
217
  /** Deployment site URL, or `null` when none is configured/detected. */
209
218
  site: string | null;
@@ -213,8 +222,8 @@ export interface BlumeDataConfig {
213
222
  /** Table-of-contents settings: whether to show it and the heading range. */
214
223
  toc: ResolvedConfig["toc"];
215
224
  /**
216
- * WebMCP in-page tools (`ai.webmcp`), plus whether llms.txt exists for the
217
- * list tool to fetch (`ai.llmsTxt.enabled`).
225
+ * WebMCP in-page tools (`agents.webmcp`), plus whether llms.txt exists for the
226
+ * list tool to fetch (`agents.llmsTxt.enabled`).
218
227
  */
219
228
  /** Docs versioning config; `null` when the site is unversioned. */
220
229
  versions: NonNullable<ResolvedConfig["versions"]> | null;
@@ -223,6 +232,16 @@ export interface BlumeDataConfig {
223
232
  x: { creator?: string; handle?: string };
224
233
  }
225
234
 
235
+ /**
236
+ * The `discovery` flags the head partial (`components/layout/DiscoveryLinks.astro`)
237
+ * advertises — every layout's `discovery` prop is typed from here so a renamed
238
+ * or added flag surfaces in the shells at typecheck instead of drifting.
239
+ */
240
+ export type DiscoveryHeadLinks = Pick<
241
+ BlumeDataConfig["discovery"],
242
+ "agentReadability" | "aiCatalog" | "llmsTxt"
243
+ >;
244
+
226
245
  /**
227
246
  * The compact snapshot the layout serializes into the page for React island
228
247
  * hooks (`blume/hooks`). Islands hydrate independently, so this is read from a
@@ -19,22 +19,25 @@ export interface IslandDescriptor {
19
19
  // oxlint-disable-next-line anti-slop/no-unknown-type-aliases -- inherits the untyped `ComponentReference` above
20
20
  export type ComponentOverride = ComponentReference | IslandDescriptor;
21
21
 
22
- /** User-authored component overrides, grouped by surface. */
22
+ /**
23
+ * User-authored component overrides, grouped by surface. Blume reads this file
24
+ * statically (never executing it), so every entry must be an imported
25
+ * identifier, a path string, or a `{ component, client, media }` object literal
26
+ * — an entry with a `client` mode is an island, hydrated through a generated
27
+ * wrapper.
28
+ */
23
29
  // oxlint-disable anti-slop/no-unsafe-dictionary-type -- `ComponentOverride` is untyped by
24
30
  // design: user configs pass imported components from any framework (React
25
31
  // functions, Svelte classes, Vue SFC objects), which share no structural type.
26
32
  // `resolveSlot` and the generated components map are the runtime boundary.
27
33
  export interface ComponentOverrides {
28
- /**
29
- * Interactive framework components made available in every `.mdx` page. Like
30
- * `mdx`, but hydrated: entries default to `client: "visible"`. Shorthand for
31
- * an `mdx` descriptor with a client mode, and the config-file equivalent of
32
- * dropping a component in the `islands/` folder.
33
- */
34
- islands?: Record<string, ComponentOverride>;
35
34
  /** Layout slot overrides (`Header`, `Sidebar`, `Footer`, ...). */
36
35
  layout?: Record<string, ComponentOverride>;
37
- /** MDX component map overrides (`Callout`, `Card`, ...). */
36
+ /**
37
+ * MDX component map overrides (`Callout`, `Card`, ...) and additions,
38
+ * available in every `.mdx` page. Give an entry a `client` mode to hydrate
39
+ * it — the config-file equivalent of dropping a component in `islands/`.
40
+ */
38
41
  mdx?: Record<string, ComponentOverride>;
39
42
  }
40
43
  // oxlint-enable anti-slop/no-unsafe-dictionary-type
@@ -1,87 +1,31 @@
1
+ import { inferDeploymentSite } from "../deploy/platforms/index.ts";
1
2
  import type { ResolvedConfig } from "./schema.ts";
2
3
 
3
- /** The deployment platforms Blume can infer from runtime/CI env vars. */
4
- type DeploymentAdapter = NonNullable<ResolvedConfig["deployment"]["adapter"]>;
5
-
6
- interface Platform {
7
- /** Astro adapter to use when building for server output on this platform. */
8
- adapter: DeploymentAdapter;
9
- /** True when the env indicates the build is running on this platform. */
10
- detect: (env: NodeJS.ProcessEnv) => boolean;
11
- /** Resolve the canonical site URL from the platform's env vars, or null. */
12
- site: (env: NodeJS.ProcessEnv) => string | null;
13
- }
14
-
15
- /** Prefix a bare host with `https://`; pass values that are already absolute. */
16
- const toUrl = (value: string | undefined): string | null => {
17
- const trimmed = value?.trim();
18
- if (!trimmed) {
19
- return null;
20
- }
21
- return /^https?:\/\//u.test(trimmed) ? trimmed : `https://${trimmed}`;
22
- };
23
-
24
- /**
25
- * Platforms checked in order; the first whose `detect` matches wins. Site URLs
26
- * prefer the stable production domain over per-deployment preview URLs so the
27
- * inferred origin (sitemap, OG, RSS) stays put across deploys.
28
- */
29
- const PLATFORMS: Platform[] = [
30
- {
31
- adapter: "vercel",
32
- detect: (env) => Boolean(env.VERCEL),
33
- // Fall through per *resolved* value, not per variable — a platform can set
34
- // a var to the empty string, which `??` on the raw values treats as
35
- // present, dead-ending the chain and silently losing the site URL.
36
- site: (env) =>
37
- toUrl(env.VERCEL_PROJECT_PRODUCTION_URL) ?? toUrl(env.VERCEL_URL),
38
- },
39
- {
40
- adapter: "netlify",
41
- detect: (env) => Boolean(env.NETLIFY),
42
- site: (env) =>
43
- toUrl(env.URL) ?? toUrl(env.DEPLOY_PRIME_URL) ?? toUrl(env.DEPLOY_URL),
44
- },
45
- {
46
- adapter: "cloudflare",
47
- detect: (env) => Boolean(env.CF_PAGES),
48
- site: (env) => toUrl(env.CF_PAGES_URL),
49
- },
50
- ];
51
-
52
4
  /**
53
- * Adapters whose `deployment.site` arrives from platform env vars at deploy
54
- * time. Consumers (e.g. the audit) use this to tell "site is missing" apart
55
- * from "site is missing *here*, but the platform will set it".
56
- */
57
- export const SITE_INFERRING_ADAPTERS: ReadonlySet<string> = new Set(
58
- PLATFORMS.map((platform) => platform.adapter)
59
- );
60
-
61
- /**
62
- * Fill in `deployment.adapter` and `deployment.site` from platform env vars
63
- * (Vercel, Netlify, Cloudflare Pages) when the user hasn't set them. Explicit
64
- * config always wins, and the adapter is only inferred for server output (it
65
- * has no effect on static builds). Mirrors Astro's platform auto-detection so a
66
- * project deployed to a known host gets a working canonical origin for free.
5
+ * Fill in the deployment `site` from platform env vars (Vercel, Netlify,
6
+ * Cloudflare Pages) when the config hasn't set one. Explicit config always
7
+ * wins. Each adapter's platform declares its own detection and URL vars (see
8
+ * `deploy/platforms/*`); the configured adapter is asked first, then every
9
+ * other platform, so a static build deployed to a known host gets a working
10
+ * canonical origin for free, mirroring Astro's platform auto-detection.
67
11
  */
68
12
  export const applyDeploymentEnv = (
69
13
  config: ResolvedConfig,
70
14
  env: NodeJS.ProcessEnv = process.env
71
15
  ): ResolvedConfig => {
72
- const platform = PLATFORMS.find((candidate) => candidate.detect(env));
73
- if (!platform) {
16
+ const { deployment } = config;
17
+ if (deployment.options.site) {
74
18
  return config;
75
19
  }
76
-
77
- const { deployment } = config;
78
- const adapter =
79
- deployment.adapter ??
80
- (deployment.output === "server" ? platform.adapter : null);
81
- const site = deployment.site ?? platform.site(env) ?? undefined;
82
-
83
- if (adapter === deployment.adapter && site === deployment.site) {
20
+ const site = inferDeploymentSite(deployment, env);
21
+ if (!site) {
84
22
  return config;
85
23
  }
86
- return { ...config, deployment: { ...deployment, adapter, site } };
24
+ return {
25
+ ...config,
26
+ deployment: {
27
+ ...deployment,
28
+ options: { ...deployment.options, site },
29
+ },
30
+ };
87
31
  };