@wildo-ai/saas-website 1.1.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 (383) hide show
  1. package/LICENSE +34 -0
  2. package/dist/esm/.builder.pid +9 -0
  3. package/dist/esm/astro/blog-post-bridge.d.ts +324 -0
  4. package/dist/esm/astro/blog-post-bridge.d.ts.map +1 -0
  5. package/dist/esm/astro/blog-post-bridge.js +57 -0
  6. package/dist/esm/astro/blog-post-bridge.js.map +1 -0
  7. package/dist/esm/astro/blog-post-head.renderer.d.ts +129 -0
  8. package/dist/esm/astro/blog-post-head.renderer.d.ts.map +1 -0
  9. package/dist/esm/astro/blog-post-head.renderer.js +139 -0
  10. package/dist/esm/astro/blog-post-head.renderer.js.map +1 -0
  11. package/dist/esm/astro/bridge-runtime.d.ts +224 -0
  12. package/dist/esm/astro/bridge-runtime.d.ts.map +1 -0
  13. package/dist/esm/astro/bridge-runtime.js +30 -0
  14. package/dist/esm/astro/bridge-runtime.js.map +1 -0
  15. package/dist/esm/astro/collect-expected-label-keys.d.ts +65 -0
  16. package/dist/esm/astro/collect-expected-label-keys.d.ts.map +1 -0
  17. package/dist/esm/astro/collect-expected-label-keys.js +101 -0
  18. package/dist/esm/astro/collect-expected-label-keys.js.map +1 -0
  19. package/dist/esm/astro/headers-renderer.d.ts +32 -0
  20. package/dist/esm/astro/headers-renderer.d.ts.map +1 -0
  21. package/dist/esm/astro/headers-renderer.js +64 -0
  22. package/dist/esm/astro/headers-renderer.js.map +1 -0
  23. package/dist/esm/astro/i18n-routing.helper.d.ts +91 -0
  24. package/dist/esm/astro/i18n-routing.helper.d.ts.map +1 -0
  25. package/dist/esm/astro/i18n-routing.helper.js +23 -0
  26. package/dist/esm/astro/i18n-routing.helper.js.map +1 -0
  27. package/dist/esm/astro/internal/html-escape.d.ts +31 -0
  28. package/dist/esm/astro/internal/html-escape.d.ts.map +1 -0
  29. package/dist/esm/astro/internal/html-escape.js +40 -0
  30. package/dist/esm/astro/internal/html-escape.js.map +1 -0
  31. package/dist/esm/astro/label-pack-loader.d.ts +134 -0
  32. package/dist/esm/astro/label-pack-loader.d.ts.map +1 -0
  33. package/dist/esm/astro/label-pack-loader.js +298 -0
  34. package/dist/esm/astro/label-pack-loader.js.map +1 -0
  35. package/dist/esm/astro/llms-txt-server.d.ts +28 -0
  36. package/dist/esm/astro/llms-txt-server.d.ts.map +1 -0
  37. package/dist/esm/astro/llms-txt-server.js +33 -0
  38. package/dist/esm/astro/llms-txt-server.js.map +1 -0
  39. package/dist/esm/astro/pick-labels-for-page.d.ts +63 -0
  40. package/dist/esm/astro/pick-labels-for-page.d.ts.map +1 -0
  41. package/dist/esm/astro/pick-labels-for-page.js +73 -0
  42. package/dist/esm/astro/pick-labels-for-page.js.map +1 -0
  43. package/dist/esm/astro/robots-renderer.d.ts +85 -0
  44. package/dist/esm/astro/robots-renderer.d.ts.map +1 -0
  45. package/dist/esm/astro/robots-renderer.js +157 -0
  46. package/dist/esm/astro/robots-renderer.js.map +1 -0
  47. package/dist/esm/astro/sitemap-coverage.d.ts +101 -0
  48. package/dist/esm/astro/sitemap-coverage.d.ts.map +1 -0
  49. package/dist/esm/astro/sitemap-coverage.js +67 -0
  50. package/dist/esm/astro/sitemap-coverage.js.map +1 -0
  51. package/dist/esm/astro/structured-data.renderer.d.ts +21 -0
  52. package/dist/esm/astro/structured-data.renderer.d.ts.map +1 -0
  53. package/dist/esm/astro/structured-data.renderer.js +142 -0
  54. package/dist/esm/astro/structured-data.renderer.js.map +1 -0
  55. package/dist/esm/astro/website-page-head.renderer.d.ts +93 -0
  56. package/dist/esm/astro/website-page-head.renderer.d.ts.map +1 -0
  57. package/dist/esm/astro/website-page-head.renderer.js +184 -0
  58. package/dist/esm/astro/website-page-head.renderer.js.map +1 -0
  59. package/dist/esm/astro/website-page-runtime.helper.d.ts +112 -0
  60. package/dist/esm/astro/website-page-runtime.helper.d.ts.map +1 -0
  61. package/dist/esm/astro/website-page-runtime.helper.js +60 -0
  62. package/dist/esm/astro/website-page-runtime.helper.js.map +1 -0
  63. package/dist/esm/astro/website-site-context.d.ts +126 -0
  64. package/dist/esm/astro/website-site-context.d.ts.map +1 -0
  65. package/dist/esm/astro/website-site-context.js +37 -0
  66. package/dist/esm/astro/website-site-context.js.map +1 -0
  67. package/dist/esm/astro-island.d.ts +56 -0
  68. package/dist/esm/astro-island.d.ts.map +1 -0
  69. package/dist/esm/astro-island.js +61 -0
  70. package/dist/esm/astro-island.js.map +1 -0
  71. package/dist/esm/astro.d.ts +151 -0
  72. package/dist/esm/astro.d.ts.map +1 -0
  73. package/dist/esm/astro.js +151 -0
  74. package/dist/esm/astro.js.map +1 -0
  75. package/dist/esm/companion-exports.d.ts +38 -0
  76. package/dist/esm/companion-exports.d.ts.map +1 -0
  77. package/dist/esm/companion-exports.js +38 -0
  78. package/dist/esm/companion-exports.js.map +1 -0
  79. package/dist/esm/components/low-level/WebsiteButton.d.ts +73 -0
  80. package/dist/esm/components/low-level/WebsiteButton.d.ts.map +1 -0
  81. package/dist/esm/components/low-level/WebsiteButton.js +68 -0
  82. package/dist/esm/components/low-level/WebsiteButton.js.map +1 -0
  83. package/dist/esm/components/low-level/WebsiteHeading.d.ts +78 -0
  84. package/dist/esm/components/low-level/WebsiteHeading.d.ts.map +1 -0
  85. package/dist/esm/components/low-level/WebsiteHeading.js +41 -0
  86. package/dist/esm/components/low-level/WebsiteHeading.js.map +1 -0
  87. package/dist/esm/components/low-level/WebsiteImage.d.ts +73 -0
  88. package/dist/esm/components/low-level/WebsiteImage.d.ts.map +1 -0
  89. package/dist/esm/components/low-level/WebsiteImage.js +21 -0
  90. package/dist/esm/components/low-level/WebsiteImage.js.map +1 -0
  91. package/dist/esm/components/low-level/WebsiteInternalButton.d.ts +90 -0
  92. package/dist/esm/components/low-level/WebsiteInternalButton.d.ts.map +1 -0
  93. package/dist/esm/components/low-level/WebsiteInternalButton.js +47 -0
  94. package/dist/esm/components/low-level/WebsiteInternalButton.js.map +1 -0
  95. package/dist/esm/components/low-level/WebsiteInternalLink.d.ts +99 -0
  96. package/dist/esm/components/low-level/WebsiteInternalLink.d.ts.map +1 -0
  97. package/dist/esm/components/low-level/WebsiteInternalLink.js +68 -0
  98. package/dist/esm/components/low-level/WebsiteInternalLink.js.map +1 -0
  99. package/dist/esm/components/low-level/WebsiteLink.d.ts +50 -0
  100. package/dist/esm/components/low-level/WebsiteLink.d.ts.map +1 -0
  101. package/dist/esm/components/low-level/WebsiteLink.js +22 -0
  102. package/dist/esm/components/low-level/WebsiteLink.js.map +1 -0
  103. package/dist/esm/components/low-level/WebsiteText.d.ts +57 -0
  104. package/dist/esm/components/low-level/WebsiteText.d.ts.map +1 -0
  105. package/dist/esm/components/low-level/WebsiteText.js +57 -0
  106. package/dist/esm/components/low-level/WebsiteText.js.map +1 -0
  107. package/dist/esm/config/define-website-config.d.ts +83 -0
  108. package/dist/esm/config/define-website-config.d.ts.map +1 -0
  109. package/dist/esm/config/define-website-config.js +126 -0
  110. package/dist/esm/config/define-website-config.js.map +1 -0
  111. package/dist/esm/config/index.d.ts +38 -0
  112. package/dist/esm/config/index.d.ts.map +1 -0
  113. package/dist/esm/config/index.js +38 -0
  114. package/dist/esm/config/index.js.map +1 -0
  115. package/dist/esm/config/load-website-config.d.ts +136 -0
  116. package/dist/esm/config/load-website-config.d.ts.map +1 -0
  117. package/dist/esm/config/load-website-config.js +177 -0
  118. package/dist/esm/config/load-website-config.js.map +1 -0
  119. package/dist/esm/config/wildo-website-config.schemas.d.ts +251 -0
  120. package/dist/esm/config/wildo-website-config.schemas.d.ts.map +1 -0
  121. package/dist/esm/config/wildo-website-config.schemas.js +302 -0
  122. package/dist/esm/config/wildo-website-config.schemas.js.map +1 -0
  123. package/dist/esm/config-loader.d.ts +35 -0
  124. package/dist/esm/config-loader.d.ts.map +1 -0
  125. package/dist/esm/config-loader.js +35 -0
  126. package/dist/esm/config-loader.js.map +1 -0
  127. package/dist/esm/core/anonymous-session/InboundContactForm.d.ts +38 -0
  128. package/dist/esm/core/anonymous-session/InboundContactForm.d.ts.map +1 -0
  129. package/dist/esm/core/anonymous-session/InboundContactForm.js +77 -0
  130. package/dist/esm/core/anonymous-session/InboundContactForm.js.map +1 -0
  131. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts +41 -0
  132. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts.map +1 -0
  133. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js +58 -0
  134. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js.map +1 -0
  135. package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts +81 -0
  136. package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts.map +1 -0
  137. package/dist/esm/core/anonymous-session/website-anonymous-session-client.js +177 -0
  138. package/dist/esm/core/anonymous-session/website-anonymous-session-client.js.map +1 -0
  139. package/dist/esm/core/contexts/WebsitePageContext.d.ts +40 -0
  140. package/dist/esm/core/contexts/WebsitePageContext.d.ts.map +1 -0
  141. package/dist/esm/core/contexts/WebsitePageContext.js +8 -0
  142. package/dist/esm/core/contexts/WebsitePageContext.js.map +1 -0
  143. package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts +162 -0
  144. package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts.map +1 -0
  145. package/dist/esm/core/contexts/WebsiteRuntimeContext.js +22 -0
  146. package/dist/esm/core/contexts/WebsiteRuntimeContext.js.map +1 -0
  147. package/dist/esm/core/contexts/WebsiteSectionContext.d.ts +47 -0
  148. package/dist/esm/core/contexts/WebsiteSectionContext.d.ts.map +1 -0
  149. package/dist/esm/core/contexts/WebsiteSectionContext.js +8 -0
  150. package/dist/esm/core/contexts/WebsiteSectionContext.js.map +1 -0
  151. package/dist/esm/core/contexts/useWebsitePage.d.ts +13 -0
  152. package/dist/esm/core/contexts/useWebsitePage.d.ts.map +1 -0
  153. package/dist/esm/core/contexts/useWebsitePage.js +22 -0
  154. package/dist/esm/core/contexts/useWebsitePage.js.map +1 -0
  155. package/dist/esm/core/contexts/useWebsiteRuntime.d.ts +19 -0
  156. package/dist/esm/core/contexts/useWebsiteRuntime.d.ts.map +1 -0
  157. package/dist/esm/core/contexts/useWebsiteRuntime.js +28 -0
  158. package/dist/esm/core/contexts/useWebsiteRuntime.js.map +1 -0
  159. package/dist/esm/core/contexts/useWebsiteSection.d.ts +12 -0
  160. package/dist/esm/core/contexts/useWebsiteSection.d.ts.map +1 -0
  161. package/dist/esm/core/contexts/useWebsiteSection.js +22 -0
  162. package/dist/esm/core/contexts/useWebsiteSection.js.map +1 -0
  163. package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts +17 -0
  164. package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts.map +1 -0
  165. package/dist/esm/core/external-providers/frontend-provider-registry.website.js +23 -0
  166. package/dist/esm/core/external-providers/frontend-provider-registry.website.js.map +1 -0
  167. package/dist/esm/core/factories/define-website-page-manifest.d.ts +70 -0
  168. package/dist/esm/core/factories/define-website-page-manifest.d.ts.map +1 -0
  169. package/dist/esm/core/factories/define-website-page-manifest.js +51 -0
  170. package/dist/esm/core/factories/define-website-page-manifest.js.map +1 -0
  171. package/dist/esm/core/factories/define-website-section.d.ts +101 -0
  172. package/dist/esm/core/factories/define-website-section.d.ts.map +1 -0
  173. package/dist/esm/core/factories/define-website-section.js +71 -0
  174. package/dist/esm/core/factories/define-website-section.js.map +1 -0
  175. package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts +23 -0
  176. package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts.map +1 -0
  177. package/dist/esm/core/hooks/useWebsiteDesignTokens.js +25 -0
  178. package/dist/esm/core/hooks/useWebsiteDesignTokens.js.map +1 -0
  179. package/dist/esm/core/hooks/useWebsiteLabel.d.ts +68 -0
  180. package/dist/esm/core/hooks/useWebsiteLabel.d.ts.map +1 -0
  181. package/dist/esm/core/hooks/useWebsiteLabel.js +103 -0
  182. package/dist/esm/core/hooks/useWebsiteLabel.js.map +1 -0
  183. package/dist/esm/core/layouts/WebsitePageLayout.d.ts +87 -0
  184. package/dist/esm/core/layouts/WebsitePageLayout.d.ts.map +1 -0
  185. package/dist/esm/core/layouts/WebsitePageLayout.js +170 -0
  186. package/dist/esm/core/layouts/WebsitePageLayout.js.map +1 -0
  187. package/dist/esm/core/layouts/WebsiteSection.d.ts +91 -0
  188. package/dist/esm/core/layouts/WebsiteSection.d.ts.map +1 -0
  189. package/dist/esm/core/layouts/WebsiteSection.js +26 -0
  190. package/dist/esm/core/layouts/WebsiteSection.js.map +1 -0
  191. package/dist/esm/core/routing/internal-routing.utils.d.ts +65 -0
  192. package/dist/esm/core/routing/internal-routing.utils.d.ts.map +1 -0
  193. package/dist/esm/core/routing/internal-routing.utils.js +14 -0
  194. package/dist/esm/core/routing/internal-routing.utils.js.map +1 -0
  195. package/dist/esm/index.d.ts +129 -0
  196. package/dist/esm/index.d.ts.map +1 -0
  197. package/dist/esm/index.js +129 -0
  198. package/dist/esm/index.js.map +1 -0
  199. package/dist/esm/mdx/BlogPost.d.ts +193 -0
  200. package/dist/esm/mdx/BlogPost.d.ts.map +1 -0
  201. package/dist/esm/mdx/BlogPost.js +161 -0
  202. package/dist/esm/mdx/BlogPost.js.map +1 -0
  203. package/dist/esm/mdx/blog-post-collection.config.d.ts +139 -0
  204. package/dist/esm/mdx/blog-post-collection.config.d.ts.map +1 -0
  205. package/dist/esm/mdx/blog-post-collection.config.js +27 -0
  206. package/dist/esm/mdx/blog-post-collection.config.js.map +1 -0
  207. package/dist/esm/mdx/blog-post-frontmatter-source.d.ts +12 -0
  208. package/dist/esm/mdx/blog-post-frontmatter-source.d.ts.map +1 -0
  209. package/dist/esm/mdx/blog-post-frontmatter-source.js +13 -0
  210. package/dist/esm/mdx/blog-post-frontmatter-source.js.map +1 -0
  211. package/dist/esm/mdx/index.d.ts +22 -0
  212. package/dist/esm/mdx/index.d.ts.map +1 -0
  213. package/dist/esm/mdx/index.js +22 -0
  214. package/dist/esm/mdx/index.js.map +1 -0
  215. package/dist/esm/mdx/website-mdx-provider.d.ts +90 -0
  216. package/dist/esm/mdx/website-mdx-provider.d.ts.map +1 -0
  217. package/dist/esm/mdx/website-mdx-provider.js +8 -0
  218. package/dist/esm/mdx/website-mdx-provider.js.map +1 -0
  219. package/dist/esm/mdx.d.ts +38 -0
  220. package/dist/esm/mdx.d.ts.map +1 -0
  221. package/dist/esm/mdx.js +38 -0
  222. package/dist/esm/mdx.js.map +1 -0
  223. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts +75 -0
  224. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts.map +1 -0
  225. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js +85 -0
  226. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js.map +1 -0
  227. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts +120 -0
  228. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts.map +1 -0
  229. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js +152 -0
  230. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js.map +1 -0
  231. package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts +73 -0
  232. package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts.map +1 -0
  233. package/dist/esm/schemas/label-keys/website-label-key.schemas.js +76 -0
  234. package/dist/esm/schemas/label-keys/website-label-key.schemas.js.map +1 -0
  235. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts +209 -0
  236. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts.map +1 -0
  237. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js +218 -0
  238. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js.map +1 -0
  239. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts +431 -0
  240. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts.map +1 -0
  241. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js +438 -0
  242. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js.map +1 -0
  243. package/dist/esm/schemas/refs/page-ref.schemas.d.ts +40 -0
  244. package/dist/esm/schemas/refs/page-ref.schemas.d.ts.map +1 -0
  245. package/dist/esm/schemas/refs/page-ref.schemas.js +43 -0
  246. package/dist/esm/schemas/refs/page-ref.schemas.js.map +1 -0
  247. package/dist/esm/schemas/refs/section-ref.schemas.d.ts +41 -0
  248. package/dist/esm/schemas/refs/section-ref.schemas.d.ts.map +1 -0
  249. package/dist/esm/schemas/refs/section-ref.schemas.js +44 -0
  250. package/dist/esm/schemas/refs/section-ref.schemas.js.map +1 -0
  251. package/dist/esm/schemas/sections/website-section-category.shared.d.ts +63 -0
  252. package/dist/esm/schemas/sections/website-section-category.shared.d.ts.map +1 -0
  253. package/dist/esm/schemas/sections/website-section-category.shared.js +64 -0
  254. package/dist/esm/schemas/sections/website-section-category.shared.js.map +1 -0
  255. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts +114 -0
  256. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts.map +1 -0
  257. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js +69 -0
  258. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js.map +1 -0
  259. package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts +100 -0
  260. package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts.map +1 -0
  261. package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js +355 -0
  262. package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js.map +1 -0
  263. package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts +58 -0
  264. package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts.map +1 -0
  265. package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js +2 -0
  266. package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js.map +1 -0
  267. package/dist/esm/schemas/validators/label-pack.validator.d.ts +144 -0
  268. package/dist/esm/schemas/validators/label-pack.validator.d.ts.map +1 -0
  269. package/dist/esm/schemas/validators/label-pack.validator.js +100 -0
  270. package/dist/esm/schemas/validators/label-pack.validator.js.map +1 -0
  271. package/dist/tsconfig.build.tsbuildinfo +1 -0
  272. package/package.json +143 -0
  273. package/src/__tests__/bundle-isolation.test.ts +607 -0
  274. package/src/astro/__tests__/blog-post-bridge.test.tsx +288 -0
  275. package/src/astro/__tests__/blog-post-head.renderer.test.ts +249 -0
  276. package/src/astro/__tests__/bridge-runtime.test.tsx +198 -0
  277. package/src/astro/__tests__/collect-expected-label-keys.test.ts +69 -0
  278. package/src/astro/__tests__/headers-renderer.test.ts +143 -0
  279. package/src/astro/__tests__/i18n-routing.helper.test.ts +116 -0
  280. package/src/astro/__tests__/label-pack-loader.test.ts +305 -0
  281. package/src/astro/__tests__/llms-txt-server.test.ts +127 -0
  282. package/src/astro/__tests__/pick-labels-for-page.test.ts +60 -0
  283. package/src/astro/__tests__/robots-renderer.test.ts +228 -0
  284. package/src/astro/__tests__/sitemap-coverage.test.ts +230 -0
  285. package/src/astro/__tests__/structured-data.renderer.test.ts +172 -0
  286. package/src/astro/__tests__/website-page-head.renderer.test.ts +424 -0
  287. package/src/astro/__tests__/website-page-runtime.helper.test.ts +157 -0
  288. package/src/astro/__tests__/website-site-context.test.ts +121 -0
  289. package/src/astro/blog-post-bridge.tsx +404 -0
  290. package/src/astro/blog-post-head.renderer.ts +293 -0
  291. package/src/astro/bridge-runtime.tsx +270 -0
  292. package/src/astro/collect-expected-label-keys.ts +113 -0
  293. package/src/astro/headers-renderer.ts +82 -0
  294. package/src/astro/i18n-routing.helper.ts +116 -0
  295. package/src/astro/internal/html-escape.ts +41 -0
  296. package/src/astro/label-pack-loader.ts +385 -0
  297. package/src/astro/llms-txt-server.ts +56 -0
  298. package/src/astro/pick-labels-for-page.ts +85 -0
  299. package/src/astro/robots-renderer.ts +171 -0
  300. package/src/astro/sitemap-coverage.ts +186 -0
  301. package/src/astro/structured-data.renderer.ts +171 -0
  302. package/src/astro/website-page-head.renderer.ts +279 -0
  303. package/src/astro/website-page-runtime.helper.ts +188 -0
  304. package/src/astro/website-site-context.ts +136 -0
  305. package/src/astro-island.ts +61 -0
  306. package/src/astro.ts +151 -0
  307. package/src/companion-exports.ts +38 -0
  308. package/src/components/low-level/WebsiteButton.tsx +118 -0
  309. package/src/components/low-level/WebsiteHeading.tsx +96 -0
  310. package/src/components/low-level/WebsiteImage.tsx +96 -0
  311. package/src/components/low-level/WebsiteInternalButton.tsx +172 -0
  312. package/src/components/low-level/WebsiteInternalLink.tsx +193 -0
  313. package/src/components/low-level/WebsiteLink.tsx +71 -0
  314. package/src/components/low-level/WebsiteText.tsx +75 -0
  315. package/src/components/low-level/__tests__/WebsiteInternalButton.test.tsx +169 -0
  316. package/src/components/low-level/__tests__/WebsiteInternalLink.test.tsx +202 -0
  317. package/src/components/low-level/__tests__/primitives.test.tsx +141 -0
  318. package/src/config/__tests__/define-website-config.test.ts +231 -0
  319. package/src/config/__tests__/load-website-config.test.ts +215 -0
  320. package/src/config/define-website-config.ts +134 -0
  321. package/src/config/index.ts +38 -0
  322. package/src/config/load-website-config.ts +229 -0
  323. package/src/config/wildo-website-config.schemas.ts +322 -0
  324. package/src/config-loader.ts +35 -0
  325. package/src/core/__tests__/WebsitePageLayout.test.tsx +184 -0
  326. package/src/core/__tests__/WebsiteSection.test.tsx +85 -0
  327. package/src/core/__tests__/contexts.test.tsx +133 -0
  328. package/src/core/__tests__/core-boundary.test.ts +85 -0
  329. package/src/core/__tests__/define-website-page-manifest.test.tsx +111 -0
  330. package/src/core/__tests__/define-website-section.test.tsx +89 -0
  331. package/src/core/__tests__/useWebsiteDesignTokens.test.tsx +41 -0
  332. package/src/core/__tests__/useWebsiteLabel.test.tsx +117 -0
  333. package/src/core/anonymous-session/InboundContactForm.tsx +157 -0
  334. package/src/core/anonymous-session/__tests__/inbound-contact-form.schema.test.ts +44 -0
  335. package/src/core/anonymous-session/inbound-contact-form.schema.ts +62 -0
  336. package/src/core/anonymous-session/website-anonymous-session-client.ts +194 -0
  337. package/src/core/contexts/WebsitePageContext.tsx +52 -0
  338. package/src/core/contexts/WebsiteRuntimeContext.tsx +175 -0
  339. package/src/core/contexts/WebsiteSectionContext.tsx +59 -0
  340. package/src/core/contexts/useWebsitePage.ts +28 -0
  341. package/src/core/contexts/useWebsiteRuntime.ts +34 -0
  342. package/src/core/contexts/useWebsiteSection.ts +28 -0
  343. package/src/core/external-providers/frontend-provider-registry.website.ts +62 -0
  344. package/src/core/factories/define-website-page-manifest.ts +102 -0
  345. package/src/core/factories/define-website-section.ts +128 -0
  346. package/src/core/hooks/useWebsiteDesignTokens.ts +26 -0
  347. package/src/core/hooks/useWebsiteLabel.ts +121 -0
  348. package/src/core/layouts/WebsitePageLayout.tsx +311 -0
  349. package/src/core/layouts/WebsiteSection.tsx +139 -0
  350. package/src/core/routing/__tests__/internal-routing.utils.test.ts +134 -0
  351. package/src/core/routing/internal-routing.utils.ts +77 -0
  352. package/src/index.ts +132 -0
  353. package/src/mdx/BlogPost.tsx +296 -0
  354. package/src/mdx/__tests__/BlogPost.test.tsx +218 -0
  355. package/src/mdx/__tests__/blog-post-collection.config.test.ts +127 -0
  356. package/src/mdx/__tests__/website-mdx-provider.test.tsx +82 -0
  357. package/src/mdx/blog-post-collection.config.ts +177 -0
  358. package/src/mdx/blog-post-frontmatter-source.ts +31 -0
  359. package/src/mdx/index.ts +39 -0
  360. package/src/mdx/website-mdx-provider.tsx +95 -0
  361. package/src/mdx.ts +38 -0
  362. package/src/schemas/__tests__/blog-frontmatter.test.ts +50 -0
  363. package/src/schemas/__tests__/companion-exports-react-free.test.ts +51 -0
  364. package/src/schemas/__tests__/design-tokens.test.ts +163 -0
  365. package/src/schemas/__tests__/label-key.test.ts +46 -0
  366. package/src/schemas/__tests__/label-pack-validator.test.ts +146 -0
  367. package/src/schemas/__tests__/page-manifest.test.ts +66 -0
  368. package/src/schemas/__tests__/refs.test.ts +37 -0
  369. package/src/schemas/__tests__/root-config.test.ts +292 -0
  370. package/src/schemas/__tests__/section-definition.test.ts +47 -0
  371. package/src/schemas/__tests__/structured-data-reconciliation.test.ts +543 -0
  372. package/src/schemas/blog/blog-post-frontmatter.shared.schemas.ts +111 -0
  373. package/src/schemas/design-tokens/website-design-tokens.shared.schemas.ts +166 -0
  374. package/src/schemas/label-keys/website-label-key.schemas.ts +88 -0
  375. package/src/schemas/manifests/website-page-manifest.shared.schemas.ts +266 -0
  376. package/src/schemas/manifests/website-root-config.shared.schemas.ts +504 -0
  377. package/src/schemas/refs/page-ref.schemas.ts +49 -0
  378. package/src/schemas/refs/section-ref.schemas.ts +50 -0
  379. package/src/schemas/sections/website-section-category.shared.ts +65 -0
  380. package/src/schemas/sections/website-section-definition.shared.schemas.ts +120 -0
  381. package/src/schemas/structured-data/structured-data-reconciliation.shared.ts +579 -0
  382. package/src/schemas/structured-data/website-structured-data.shared.schemas.ts +62 -0
  383. package/src/schemas/validators/label-pack.validator.ts +201 -0
@@ -0,0 +1,139 @@
1
+ import { type BlogPostFrontmatter } from '../schemas/blog/blog-post-frontmatter.shared.schemas';
2
+ /**
3
+ * @wildo_source:part:start saas.website.blog.collection-config facet:layer:mdx facet:family:website
4
+ *
5
+ * Astro content-collection bridge for blog posts (Phase 7 D-3 = Path Z).
6
+ *
7
+ * # The Zod-version bridge problem
8
+ *
9
+ * Astro's `astro:content` ships its own bundled Zod (currently 3.x).
10
+ * Our `BlogPostFrontmatterSchema` is Zod 4 and uses Zod-4-only APIs
11
+ * (`z.iso.datetime`, `z.url(...)`, `.brand<>()`). The two cannot share
12
+ * a schema instance directly across the version boundary, and shimming
13
+ * a Zod 4 schema down to a Zod 3 schema would create either:
14
+ *
15
+ * - a hand-mirrored copy (Path X) — maintained in `src/content/config.ts`
16
+ * using Astro's `z`, with silent-drift risk every time a field is
17
+ * added/removed/refined; or
18
+ * - a runtime bridge package (Path C) — a non-trivial maintenance
19
+ * surface for a marginal gain.
20
+ *
21
+ * Path Z (this file) sidesteps the bridge entirely: the consumer's
22
+ * `src/content/config.ts` declares a `passthrough` collection schema
23
+ * that lets Astro accept any frontmatter shape; the engine then
24
+ * validates with the canonical Zod 4 schema at render time inside
25
+ * `<BlogPost>`. Astro's static site generator runs the page render
26
+ * during the build, so a malformed frontmatter still surfaces as a
27
+ * BUILD-TIME error (the `.parse()` call throws synchronously and Astro
28
+ * reports it with the page URL) — the only practical difference vs.
29
+ * Path X is the error-message stack location.
30
+ *
31
+ * # Why the engine ships an opaque shape (rather than the consumer
32
+ * importing the Astro `z` directly)
33
+ *
34
+ * Astro's content-collection API has churned across Astro 4 → 5
35
+ * (loaders moved from string-keyed `type` to a callable `loader`
36
+ * factory; the `glob()` loader's signature changed). Every consumer
37
+ * touching `defineCollection` directly inherits that churn; centralizing
38
+ * the wiring in the engine means the framework absorbs the upgrade
39
+ * cost in ONE place when Astro bumps a major.
40
+ *
41
+ * The shape returned here is `{ schema: <passthrough record> }`. The
42
+ * consumer spreads it into their `defineCollection` call:
43
+ *
44
+ * ```ts
45
+ * // examples/<app>/website/src/content/config.ts
46
+ * import { defineCollection, z } from 'astro:content';
47
+ * import { buildBlogPostCollectionConfig } from '@wildo-ai/saas-website/mdx';
48
+ *
49
+ * export const collections = {
50
+ * blog: defineCollection({
51
+ * type: 'content',
52
+ * ...buildBlogPostCollectionConfig({ astroZ: z }),
53
+ * }),
54
+ * };
55
+ * ```
56
+ *
57
+ * The consumer passes Astro's own `z` in (because the engine cannot
58
+ * import `astro:content` — that virtual module only exists inside
59
+ * the Astro build context, never at the engine package's compile
60
+ * time, and importing it would also pull `astro` into the engine's
61
+ * walked closure which the bundle-isolation test forbids). The engine
62
+ * builds a passthrough `z.object({}).passthrough()` from the supplied
63
+ * factory and returns the schema slot.
64
+ *
65
+ * # `parseBlogPostFrontmatter`
66
+ *
67
+ * Companion render-time validator. Called at the top of `<BlogPost>`
68
+ * with the raw `entry.data` Astro hands the page; returns the
69
+ * branded, validated `BlogPostFrontmatter` (Zod 4) or throws with
70
+ * the standard Zod-4 issue formatting + a `[blog-post]` prefix that
71
+ * tells the SSG operator which file to fix.
72
+ *
73
+ * # Boundary
74
+ *
75
+ * This file is React-runtime-safe: it only imports the (also
76
+ * React-safe) `BlogPostFrontmatterSchema` from `schemas/blog/`. It
77
+ * ships into the React-island bundle via the `mdx.ts` barrel, which
78
+ * the bundle-isolation test walks as a dedicated entry. Helpers that
79
+ * parse raw MDX source live in `blog-post-frontmatter-source.ts` so the
80
+ * `yaml` package stays on the build-time/Node side of the boundary.
81
+ */
82
+ /**
83
+ * Minimal contract for the Astro-side Zod factory we accept. Typed
84
+ * structurally (rather than imported from `astro:content`) so the
85
+ * engine package can compile/test without an Astro install. Astro's
86
+ * actual `z.object` returns a much richer Zod-3 schema; we narrow to
87
+ * just the `.passthrough()` call we make below.
88
+ */
89
+ export interface AstroZodFactoryShape {
90
+ object: (shape: Record<string, never>) => {
91
+ passthrough: () => unknown;
92
+ };
93
+ }
94
+ export interface BuildBlogPostCollectionConfigOptions {
95
+ /**
96
+ * Astro's bundled `z` object — pass `import { z } from 'astro:content'`
97
+ * from the consumer-side `src/content/config.ts`. The engine cannot
98
+ * import `astro:content` itself (virtual module, only present inside
99
+ * the Astro build pipeline; would also bloat the bundle-isolation
100
+ * walked closure with the `astro` runtime).
101
+ */
102
+ astroZ: AstroZodFactoryShape;
103
+ }
104
+ export interface BlogPostCollectionConfigShape {
105
+ /**
106
+ * The schema slot consumed by Astro's `defineCollection({...})`.
107
+ * A `passthrough` record (no field constraints at this layer) so
108
+ * Astro accepts any frontmatter; the strict Zod-4 validation runs
109
+ * at render time inside `<BlogPost>` via
110
+ * `parseBlogPostFrontmatter(...)`.
111
+ */
112
+ schema: unknown;
113
+ }
114
+ export declare function buildBlogPostCollectionConfig(opts: BuildBlogPostCollectionConfigOptions): BlogPostCollectionConfigShape;
115
+ /**
116
+ * Strict Zod-4 validator for blog-post frontmatter. Called at the top
117
+ * of `<BlogPost>` rendering against `entry.data` (whatever Astro's
118
+ * passthrough collection schema accepted). Throws on validation
119
+ * failure with a `[blog-post]`-prefixed message that points to the
120
+ * offending file via the surrounding render call site.
121
+ *
122
+ * @param raw — the unvalidated frontmatter object Astro supplies
123
+ * (`entry.data` from `getEntry('blog', slug)` or `getCollection('blog')`).
124
+ * @param ctx — diagnostic context appended to the error message so
125
+ * the consumer can find the failing source file when SSG halts.
126
+ * Optional but recommended.
127
+ */
128
+ export interface ParseBlogPostFrontmatterContext {
129
+ /**
130
+ * The MDX file's path or slug. Echoed into the error message when
131
+ * validation fails so the operator can grep for it. Astro typically
132
+ * gives consumers `entry.id` (the slug + extension) — passing it
133
+ * through here is enough for an actionable error.
134
+ */
135
+ readonly source?: string;
136
+ }
137
+ export declare function parseBlogPostFrontmatter(raw: unknown, ctx?: ParseBlogPostFrontmatterContext): BlogPostFrontmatter;
138
+ /** @wildo_source:part:end saas.website.blog.collection-config */
139
+ //# sourceMappingURL=blog-post-collection.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blog-post-collection.config.d.ts","sourceRoot":"","sources":["../../../../src/mdx/blog-post-collection.config.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,sDAAsD,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK;QACxC,WAAW,EAAE,MAAM,OAAO,CAAC;KAC5B,CAAC;CACH;AAED,MAAM,WAAW,oCAAoC;IACnD;;;;;;OAMG;IACH,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,6BAA6B;IAC5C;;;;;;OAMG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,oCAAoC,GACzC,6BAA6B,CAK/B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,+BAA+B;IAC9C;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,OAAO,EACZ,GAAG,GAAE,+BAAoC,GACxC,mBAAmB,CAkBrB;AACD,iEAAiE"}
@@ -0,0 +1,27 @@
1
+ import { formatZodIssues } from '@wildo-ai/saas-models/public-runtime';
2
+ import { BlogPostFrontmatterSchema, } from '../schemas/blog/blog-post-frontmatter.shared.schemas.js';
3
+ export function buildBlogPostCollectionConfig(opts) {
4
+ const { astroZ } = opts;
5
+ return {
6
+ schema: astroZ.object({}).passthrough(),
7
+ };
8
+ }
9
+ export function parseBlogPostFrontmatter(raw, ctx = {}) {
10
+ const result = BlogPostFrontmatterSchema.safeParse(raw);
11
+ if (result.success) {
12
+ return result.data;
13
+ }
14
+ const sourceSuffix = ctx.source !== undefined ? ` (source="${ctx.source}")` : '';
15
+ /**
16
+ * Zod 4's `result.error.message` is the JSON-stringified `issues[]` array —
17
+ * long-form, it floods the Astro build log, and the path is what an operator
18
+ * needs to find the broken frontmatter field. `formatZodIssues` is the
19
+ * framework-canonical rendering (one `path: message` per entry); we only own
20
+ * the bullet prefix. Unbounded on purpose: every bad field in a post should
21
+ * be fixable from one build run.
22
+ */
23
+ const issueLines = formatZodIssues(result.error.issues).map((entry) => ` - ${entry}`);
24
+ throw new Error(`[blog-post] Frontmatter failed BlogPostFrontmatterSchema validation${sourceSuffix}:\n${issueLines.join('\n')}`);
25
+ }
26
+ /** @wildo_source:part:end saas.website.blog.collection-config */
27
+ //# sourceMappingURL=blog-post-collection.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blog-post-collection.config.js","sourceRoot":"","sources":["../../../../src/mdx/blog-post-collection.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EACL,yBAAyB,GAE1B,MAAM,sDAAsD,CAAC;AAsH9D,MAAM,UAAU,6BAA6B,CAC3C,IAA0C;IAE1C,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE;KACxC,CAAC;AACJ,CAAC;AAyBD,MAAM,UAAU,wBAAwB,CACtC,GAAY,EACZ,MAAuC,EAAE;IAEzC,MAAM,MAAM,GAAG,yBAAyB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IACD,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF;;;;;;;OAOG;IACH,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;IACvF,MAAM,IAAI,KAAK,CACb,sEAAsE,YAAY,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChH,CAAC;AACJ,CAAC;AACD,iEAAiE","sourcesContent":["import { formatZodIssues } from '@wildo-ai/saas-models/public-runtime';\nimport {\n BlogPostFrontmatterSchema,\n type BlogPostFrontmatter,\n} from '../schemas/blog/blog-post-frontmatter.shared.schemas';\n\n/**\n * @wildo_source:part:start saas.website.blog.collection-config facet:layer:mdx facet:family:website\n *\n * Astro content-collection bridge for blog posts (Phase 7 D-3 = Path Z).\n *\n * # The Zod-version bridge problem\n *\n * Astro's `astro:content` ships its own bundled Zod (currently 3.x).\n * Our `BlogPostFrontmatterSchema` is Zod 4 and uses Zod-4-only APIs\n * (`z.iso.datetime`, `z.url(...)`, `.brand<>()`). The two cannot share\n * a schema instance directly across the version boundary, and shimming\n * a Zod 4 schema down to a Zod 3 schema would create either:\n *\n * - a hand-mirrored copy (Path X) — maintained in `src/content/config.ts`\n * using Astro's `z`, with silent-drift risk every time a field is\n * added/removed/refined; or\n * - a runtime bridge package (Path C) — a non-trivial maintenance\n * surface for a marginal gain.\n *\n * Path Z (this file) sidesteps the bridge entirely: the consumer's\n * `src/content/config.ts` declares a `passthrough` collection schema\n * that lets Astro accept any frontmatter shape; the engine then\n * validates with the canonical Zod 4 schema at render time inside\n * `<BlogPost>`. Astro's static site generator runs the page render\n * during the build, so a malformed frontmatter still surfaces as a\n * BUILD-TIME error (the `.parse()` call throws synchronously and Astro\n * reports it with the page URL) — the only practical difference vs.\n * Path X is the error-message stack location.\n *\n * # Why the engine ships an opaque shape (rather than the consumer\n * importing the Astro `z` directly)\n *\n * Astro's content-collection API has churned across Astro 4 → 5\n * (loaders moved from string-keyed `type` to a callable `loader`\n * factory; the `glob()` loader's signature changed). Every consumer\n * touching `defineCollection` directly inherits that churn; centralizing\n * the wiring in the engine means the framework absorbs the upgrade\n * cost in ONE place when Astro bumps a major.\n *\n * The shape returned here is `{ schema: <passthrough record> }`. The\n * consumer spreads it into their `defineCollection` call:\n *\n * ```ts\n * // examples/<app>/website/src/content/config.ts\n * import { defineCollection, z } from 'astro:content';\n * import { buildBlogPostCollectionConfig } from '@wildo-ai/saas-website/mdx';\n *\n * export const collections = {\n * blog: defineCollection({\n * type: 'content',\n * ...buildBlogPostCollectionConfig({ astroZ: z }),\n * }),\n * };\n * ```\n *\n * The consumer passes Astro's own `z` in (because the engine cannot\n * import `astro:content` — that virtual module only exists inside\n * the Astro build context, never at the engine package's compile\n * time, and importing it would also pull `astro` into the engine's\n * walked closure which the bundle-isolation test forbids). The engine\n * builds a passthrough `z.object({}).passthrough()` from the supplied\n * factory and returns the schema slot.\n *\n * # `parseBlogPostFrontmatter`\n *\n * Companion render-time validator. Called at the top of `<BlogPost>`\n * with the raw `entry.data` Astro hands the page; returns the\n * branded, validated `BlogPostFrontmatter` (Zod 4) or throws with\n * the standard Zod-4 issue formatting + a `[blog-post]` prefix that\n * tells the SSG operator which file to fix.\n *\n * # Boundary\n *\n * This file is React-runtime-safe: it only imports the (also\n * React-safe) `BlogPostFrontmatterSchema` from `schemas/blog/`. It\n * ships into the React-island bundle via the `mdx.ts` barrel, which\n * the bundle-isolation test walks as a dedicated entry. Helpers that\n * parse raw MDX source live in `blog-post-frontmatter-source.ts` so the\n * `yaml` package stays on the build-time/Node side of the boundary.\n */\n\n/**\n * Minimal contract for the Astro-side Zod factory we accept. Typed\n * structurally (rather than imported from `astro:content`) so the\n * engine package can compile/test without an Astro install. Astro's\n * actual `z.object` returns a much richer Zod-3 schema; we narrow to\n * just the `.passthrough()` call we make below.\n */\nexport interface AstroZodFactoryShape {\n object: (shape: Record<string, never>) => {\n passthrough: () => unknown;\n };\n}\n\nexport interface BuildBlogPostCollectionConfigOptions {\n /**\n * Astro's bundled `z` object — pass `import { z } from 'astro:content'`\n * from the consumer-side `src/content/config.ts`. The engine cannot\n * import `astro:content` itself (virtual module, only present inside\n * the Astro build pipeline; would also bloat the bundle-isolation\n * walked closure with the `astro` runtime).\n */\n astroZ: AstroZodFactoryShape;\n}\n\nexport interface BlogPostCollectionConfigShape {\n /**\n * The schema slot consumed by Astro's `defineCollection({...})`.\n * A `passthrough` record (no field constraints at this layer) so\n * Astro accepts any frontmatter; the strict Zod-4 validation runs\n * at render time inside `<BlogPost>` via\n * `parseBlogPostFrontmatter(...)`.\n */\n schema: unknown;\n}\n\nexport function buildBlogPostCollectionConfig(\n opts: BuildBlogPostCollectionConfigOptions,\n): BlogPostCollectionConfigShape {\n const { astroZ } = opts;\n return {\n schema: astroZ.object({}).passthrough(),\n };\n}\n\n/**\n * Strict Zod-4 validator for blog-post frontmatter. Called at the top\n * of `<BlogPost>` rendering against `entry.data` (whatever Astro's\n * passthrough collection schema accepted). Throws on validation\n * failure with a `[blog-post]`-prefixed message that points to the\n * offending file via the surrounding render call site.\n *\n * @param raw — the unvalidated frontmatter object Astro supplies\n * (`entry.data` from `getEntry('blog', slug)` or `getCollection('blog')`).\n * @param ctx — diagnostic context appended to the error message so\n * the consumer can find the failing source file when SSG halts.\n * Optional but recommended.\n */\nexport interface ParseBlogPostFrontmatterContext {\n /**\n * The MDX file's path or slug. Echoed into the error message when\n * validation fails so the operator can grep for it. Astro typically\n * gives consumers `entry.id` (the slug + extension) — passing it\n * through here is enough for an actionable error.\n */\n readonly source?: string;\n}\n\nexport function parseBlogPostFrontmatter(\n raw: unknown,\n ctx: ParseBlogPostFrontmatterContext = {},\n): BlogPostFrontmatter {\n const result = BlogPostFrontmatterSchema.safeParse(raw);\n if (result.success) {\n return result.data;\n }\n const sourceSuffix = ctx.source !== undefined ? ` (source=\"${ctx.source}\")` : '';\n /**\n * Zod 4's `result.error.message` is the JSON-stringified `issues[]` array —\n * long-form, it floods the Astro build log, and the path is what an operator\n * needs to find the broken frontmatter field. `formatZodIssues` is the\n * framework-canonical rendering (one `path: message` per entry); we only own\n * the bullet prefix. Unbounded on purpose: every bad field in a post should\n * be fixable from one build run.\n */\n const issueLines = formatZodIssues(result.error.issues).map((entry) => ` - ${entry}`);\n throw new Error(\n `[blog-post] Frontmatter failed BlogPostFrontmatterSchema validation${sourceSuffix}:\\n${issueLines.join('\\n')}`,\n );\n}\n/** @wildo_source:part:end saas.website.blog.collection-config */\n"]}
@@ -0,0 +1,12 @@
1
+ import { type ParseBlogPostFrontmatterContext } from './blog-post-collection.config';
2
+ import type { BlogPostFrontmatter } from '../schemas/blog/blog-post-frontmatter.shared.schemas';
3
+ /**
4
+ * Build-time helper for code that reads raw MDX files from disk and
5
+ * needs the canonical Zod-4 blog frontmatter validation. This module is
6
+ * intentionally kept out of `@wildo-ai/saas-website/mdx`, because its
7
+ * `yaml` dependency belongs to the Node/build-time graph, not the
8
+ * React-island bundle walked by the D12 isolation test.
9
+ */
10
+ export type ParseBlogPostFrontmatterFromMdxSourceContext = ParseBlogPostFrontmatterContext;
11
+ export declare function parseBlogPostFrontmatterFromMdxSource(source: string, ctx?: ParseBlogPostFrontmatterFromMdxSourceContext): BlogPostFrontmatter;
12
+ //# sourceMappingURL=blog-post-frontmatter-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blog-post-frontmatter-source.d.ts","sourceRoot":"","sources":["../../../../src/mdx/blog-post-frontmatter-source.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sDAAsD,CAAC;AAEhG;;;;;;GAMG;AACH,MAAM,MAAM,4CAA4C,GAAG,+BAA+B,CAAC;AAE3F,wBAAgB,qCAAqC,CACnD,MAAM,EAAE,MAAM,EACd,GAAG,GAAE,4CAAiD,GACrD,mBAAmB,CAUrB"}
@@ -0,0 +1,13 @@
1
+ import { parse as parseYaml } from 'yaml';
2
+ import { parseBlogPostFrontmatter, } from './blog-post-collection.config.js';
3
+ export function parseBlogPostFrontmatterFromMdxSource(source, ctx = {}) {
4
+ const normalizedSource = source.replace(/\r\n/g, '\n');
5
+ const match = normalizedSource.match(/^---\n([\s\S]*?)\n---(?:\n|$)/);
6
+ if (!match) {
7
+ const sourceSuffix = ctx.source !== undefined ? ` (source="${ctx.source}")` : '';
8
+ throw new Error(`[blog-post] MDX file is missing YAML frontmatter${sourceSuffix}.`);
9
+ }
10
+ const rawFrontmatter = parseYaml(match[1]);
11
+ return parseBlogPostFrontmatter(rawFrontmatter, ctx);
12
+ }
13
+ //# sourceMappingURL=blog-post-frontmatter-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blog-post-frontmatter-source.js","sourceRoot":"","sources":["../../../../src/mdx/blog-post-frontmatter-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,EACL,wBAAwB,GAEzB,MAAM,+BAA+B,CAAC;AAYvC,MAAM,UAAU,qCAAqC,CACnD,MAAc,EACd,MAAoD,EAAE;IAEtD,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACtE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,mDAAmD,YAAY,GAAG,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,cAAc,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,OAAO,wBAAwB,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC","sourcesContent":["import { parse as parseYaml } from 'yaml';\n\nimport {\n parseBlogPostFrontmatter,\n type ParseBlogPostFrontmatterContext,\n} from './blog-post-collection.config';\nimport type { BlogPostFrontmatter } from '../schemas/blog/blog-post-frontmatter.shared.schemas';\n\n/**\n * Build-time helper for code that reads raw MDX files from disk and\n * needs the canonical Zod-4 blog frontmatter validation. This module is\n * intentionally kept out of `@wildo-ai/saas-website/mdx`, because its\n * `yaml` dependency belongs to the Node/build-time graph, not the\n * React-island bundle walked by the D12 isolation test.\n */\nexport type ParseBlogPostFrontmatterFromMdxSourceContext = ParseBlogPostFrontmatterContext;\n\nexport function parseBlogPostFrontmatterFromMdxSource(\n source: string,\n ctx: ParseBlogPostFrontmatterFromMdxSourceContext = {},\n): BlogPostFrontmatter {\n const normalizedSource = source.replace(/\\r\\n/g, '\\n');\n const match = normalizedSource.match(/^---\\n([\\s\\S]*?)\\n---(?:\\n|$)/);\n if (!match) {\n const sourceSuffix = ctx.source !== undefined ? ` (source=\"${ctx.source}\")` : '';\n throw new Error(`[blog-post] MDX file is missing YAML frontmatter${sourceSuffix}.`);\n }\n\n const rawFrontmatter = parseYaml(match[1]);\n return parseBlogPostFrontmatter(rawFrontmatter, ctx);\n}\n"]}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Sub-barrel for the marketing-blog MDX adapter (Phase 7). Re-exports
3
+ * the three engine surfaces consumers wire up:
4
+ *
5
+ * - `<BlogPost>` — the per-post page renderer that strict-validates
6
+ * frontmatter + composes `WebsitePageLayout` + `WebsiteMdxProvider`.
7
+ * - `<WebsiteMdxProvider>` — the `@mdx-js/react` boundary the
8
+ * framework owns so the upstream package is swap-safe.
9
+ * - `buildBlogPostCollectionConfig(...)` + `parseBlogPostFrontmatter(...)`
10
+ * — the Astro content-collection bridge (Path Z passthrough at the
11
+ * collection layer, strict Zod-4 validation at render time). Raw
12
+ * MDX-source parsing is exported separately from `./mdx-source` so
13
+ * `yaml` stays out of the React-island graph.
14
+ *
15
+ * Re-exported through the top-level `mdx.ts` barrel so the public
16
+ * import surface is `'@wildo-ai/saas-website/mdx'` (matching the
17
+ * `astro.ts` / `astro-island.ts` naming pattern).
18
+ */
19
+ export { BlogPost, BLOG_POST_PAGE_REF, type BlogPostProps, type BlogPostMdxComponents, type BlogPostMdxComponent, } from './BlogPost';
20
+ export { buildBlogPostCollectionConfig, parseBlogPostFrontmatter, type AstroZodFactoryShape, type BuildBlogPostCollectionConfigOptions, type BlogPostCollectionConfigShape, type ParseBlogPostFrontmatterContext, } from './blog-post-collection.config';
21
+ export { WebsiteMdxProvider, type WebsiteMdxComponentsMap, type WebsiteMdxProviderProps, } from './website-mdx-provider';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mdx/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,EACxB,KAAK,oBAAoB,EACzB,KAAK,oCAAoC,EACzC,KAAK,6BAA6B,EAClC,KAAK,+BAA+B,GACrC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Sub-barrel for the marketing-blog MDX adapter (Phase 7). Re-exports
3
+ * the three engine surfaces consumers wire up:
4
+ *
5
+ * - `<BlogPost>` — the per-post page renderer that strict-validates
6
+ * frontmatter + composes `WebsitePageLayout` + `WebsiteMdxProvider`.
7
+ * - `<WebsiteMdxProvider>` — the `@mdx-js/react` boundary the
8
+ * framework owns so the upstream package is swap-safe.
9
+ * - `buildBlogPostCollectionConfig(...)` + `parseBlogPostFrontmatter(...)`
10
+ * — the Astro content-collection bridge (Path Z passthrough at the
11
+ * collection layer, strict Zod-4 validation at render time). Raw
12
+ * MDX-source parsing is exported separately from `./mdx-source` so
13
+ * `yaml` stays out of the React-island graph.
14
+ *
15
+ * Re-exported through the top-level `mdx.ts` barrel so the public
16
+ * import surface is `'@wildo-ai/saas-website/mdx'` (matching the
17
+ * `astro.ts` / `astro-island.ts` naming pattern).
18
+ */
19
+ export { BlogPost, BLOG_POST_PAGE_REF, } from './BlogPost.js';
20
+ export { buildBlogPostCollectionConfig, parseBlogPostFrontmatter, } from './blog-post-collection.config.js';
21
+ export { WebsiteMdxProvider, } from './website-mdx-provider.js';
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/mdx/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,QAAQ,EACR,kBAAkB,GAInB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,GAKzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,GAGnB,MAAM,wBAAwB,CAAC","sourcesContent":["/**\n * Sub-barrel for the marketing-blog MDX adapter (Phase 7). Re-exports\n * the three engine surfaces consumers wire up:\n *\n * - `<BlogPost>` — the per-post page renderer that strict-validates\n * frontmatter + composes `WebsitePageLayout` + `WebsiteMdxProvider`.\n * - `<WebsiteMdxProvider>` — the `@mdx-js/react` boundary the\n * framework owns so the upstream package is swap-safe.\n * - `buildBlogPostCollectionConfig(...)` + `parseBlogPostFrontmatter(...)`\n * — the Astro content-collection bridge (Path Z passthrough at the\n * collection layer, strict Zod-4 validation at render time). Raw\n * MDX-source parsing is exported separately from `./mdx-source` so\n * `yaml` stays out of the React-island graph.\n *\n * Re-exported through the top-level `mdx.ts` barrel so the public\n * import surface is `'@wildo-ai/saas-website/mdx'` (matching the\n * `astro.ts` / `astro-island.ts` naming pattern).\n */\n\nexport {\n BlogPost,\n BLOG_POST_PAGE_REF,\n type BlogPostProps,\n type BlogPostMdxComponents,\n type BlogPostMdxComponent,\n} from './BlogPost';\nexport {\n buildBlogPostCollectionConfig,\n parseBlogPostFrontmatter,\n type AstroZodFactoryShape,\n type BuildBlogPostCollectionConfigOptions,\n type BlogPostCollectionConfigShape,\n type ParseBlogPostFrontmatterContext,\n} from './blog-post-collection.config';\nexport {\n WebsiteMdxProvider,\n type WebsiteMdxComponentsMap,\n type WebsiteMdxProviderProps,\n} from './website-mdx-provider';\n"]}
@@ -0,0 +1,90 @@
1
+ import type { ComponentType, ReactNode } from 'react';
2
+ /**
3
+ * @wildo_source:part:start saas.website.blog.mdx-provider facet:layer:mdx facet:family:website
4
+ *
5
+ * `WebsiteMdxProvider` — thin wrapper around `@mdx-js/react`'s
6
+ * `MDXProvider` that scopes a consumer-supplied `components` map for
7
+ * the entire MDX subtree it wraps.
8
+ *
9
+ * # Why a framework wrapper at all (vs. consumers using `MDXProvider` directly)
10
+ *
11
+ * Three application-facing reasons:
12
+ *
13
+ * 1. **Single API surface for embedded business sections.** The framework
14
+ * owns the provider boundary so consumers
15
+ * never directly import from `@mdx-js/react` — they ship a single
16
+ * `mdxComponents` object literal and the framework picks the
17
+ * provider implementation. If `@mdx-js/react` ever splits its
18
+ * package or changes its provider semantics (it has shipped
19
+ * breaking changes between major versions before), the swap
20
+ * lands in this file with zero consumer churn.
21
+ * 2. **Bundle-isolation discipline.** `@mdx-js/react` is browser-safe
22
+ * but heavy (`mdx/types.js`, `react-context` propagation). Walling
23
+ * it behind a single re-export keeps the import surface auditable
24
+ * through the package's client-bundle boundary: the `mdx` public entry is
25
+ * checked separately and lists `@mdx-js/react` exactly once.
26
+ * 3. **`disableParentContext: false` (default) is the right default.**
27
+ * MDX 3 lets a nested `MDXProvider` inherit components from the
28
+ * parent provider, which is what we want when the per-blog-post
29
+ * provider sits inside a site-wide MDX provider used by landing-page
30
+ * islands.
31
+ * Pinning the option here makes the framework's posture explicit;
32
+ * a future change documents itself as a breaking framework decision
33
+ * rather than a silent `@mdx-js/react` default flip.
34
+ *
35
+ * # The `components` map shape
36
+ *
37
+ * The map is `Record<string, ComponentType<any>>` — every key is the
38
+ * tag name an MDX file uses (`<CTASection ref="post-cta" />` resolves
39
+ * via the `CTASection` key). Values are React components the consumer
40
+ * authored under their own `src/sections/blog.sections.tsx` and
41
+ * wrapped in `<WebsiteSection sectionRef={…} category={…}>` so the
42
+ * label-key context is established before the section's
43
+ * `useWebsiteLabel(slot)` calls fire. The framework does NOT inspect
44
+ * the shape — discipline lives in the consumer's section registry
45
+ * + the label-pack validation boundary (which proves the locale pack covers
46
+ * each section's expected keys).
47
+ *
48
+ * # Why a `ComponentType<any>` value type and not a stricter generic
49
+ *
50
+ * MDX components receive their own props (children, plus whatever the
51
+ * MDX author writes inline as JSX attributes). The type system cannot
52
+ * narrow this through the provider boundary because the MDX compiler
53
+ * does the routing at compile time. `ComponentType<any>` is the
54
+ * convention `@mdx-js/react` itself uses (`MDXComponents` in
55
+ * `mdx/types.js`) — staying compatible with the upstream type avoids
56
+ * a wrap/unwrap dance at every consumer call site.
57
+ *
58
+ * # Bundle boundary
59
+ *
60
+ * Ships into the React-island bundle (consumed transitively from
61
+ * `BlogPost.tsx` which itself sits behind the consumer's per-page
62
+ * bridge file). MUST stay clear of `node:*` and SSR-tier specifiers
63
+ * — the bundle-isolation test walks `mdx.ts` as one of its entries.
64
+ */
65
+ export interface WebsiteMdxComponentsMap {
66
+ /**
67
+ * Tag-name → component map. The MDX compiler resolves each
68
+ * `<TagName />` in a blog post's body against this object.
69
+ */
70
+ readonly [tagName: string]: ComponentType<any>;
71
+ }
72
+ export interface WebsiteMdxProviderProps {
73
+ /**
74
+ * Consumer-supplied component overrides. Keys are MDX tag names;
75
+ * values are the React components those tags resolve to.
76
+ */
77
+ components: WebsiteMdxComponentsMap;
78
+ /**
79
+ * MDX subtree (typically the compiled `<MdxBody/>` from a content
80
+ * collection entry). May render any number of provider-scoped
81
+ * components.
82
+ */
83
+ children: ReactNode;
84
+ }
85
+ export declare function WebsiteMdxProvider(props: WebsiteMdxProviderProps): ReactNode;
86
+ export declare namespace WebsiteMdxProvider {
87
+ var displayName: string;
88
+ }
89
+ /** @wildo_source:part:end saas.website.blog.mdx-provider */
90
+ //# sourceMappingURL=website-mdx-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website-mdx-provider.d.ts","sourceRoot":"","sources":["../../../../src/mdx/website-mdx-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAItD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,UAAU,EAAE,uBAAuB,CAAC;IACpC;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,SAAS,CAG5E;yBAHe,kBAAkB;;;AAKlC,4DAA4D"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { MDXProvider } from '@mdx-js/react';
3
+ export function WebsiteMdxProvider(props) {
4
+ const { components, children } = props;
5
+ return _jsx(MDXProvider, { components: components, children: children });
6
+ }
7
+ WebsiteMdxProvider.displayName = 'WebsiteMdxProvider';
8
+ //# sourceMappingURL=website-mdx-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website-mdx-provider.js","sourceRoot":"","sources":["../../../../src/mdx/website-mdx-provider.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAuF5C,MAAM,UAAU,kBAAkB,CAAC,KAA8B;IAC/D,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACvC,OAAO,KAAC,WAAW,IAAC,UAAU,EAAE,UAAU,YAAG,QAAQ,GAAe,CAAC;AACvE,CAAC;AACD,kBAAkB,CAAC,WAAW,GAAG,oBAAoB,CAAC","sourcesContent":["import type { ComponentType, ReactNode } from 'react';\n\nimport { MDXProvider } from '@mdx-js/react';\n\n/**\n * @wildo_source:part:start saas.website.blog.mdx-provider facet:layer:mdx facet:family:website\n *\n * `WebsiteMdxProvider` — thin wrapper around `@mdx-js/react`'s\n * `MDXProvider` that scopes a consumer-supplied `components` map for\n * the entire MDX subtree it wraps.\n *\n * # Why a framework wrapper at all (vs. consumers using `MDXProvider` directly)\n *\n * Three application-facing reasons:\n *\n * 1. **Single API surface for embedded business sections.** The framework\n * owns the provider boundary so consumers\n * never directly import from `@mdx-js/react` — they ship a single\n * `mdxComponents` object literal and the framework picks the\n * provider implementation. If `@mdx-js/react` ever splits its\n * package or changes its provider semantics (it has shipped\n * breaking changes between major versions before), the swap\n * lands in this file with zero consumer churn.\n * 2. **Bundle-isolation discipline.** `@mdx-js/react` is browser-safe\n * but heavy (`mdx/types.js`, `react-context` propagation). Walling\n * it behind a single re-export keeps the import surface auditable\n * through the package's client-bundle boundary: the `mdx` public entry is\n * checked separately and lists `@mdx-js/react` exactly once.\n * 3. **`disableParentContext: false` (default) is the right default.**\n * MDX 3 lets a nested `MDXProvider` inherit components from the\n * parent provider, which is what we want when the per-blog-post\n * provider sits inside a site-wide MDX provider used by landing-page\n * islands.\n * Pinning the option here makes the framework's posture explicit;\n * a future change documents itself as a breaking framework decision\n * rather than a silent `@mdx-js/react` default flip.\n *\n * # The `components` map shape\n *\n * The map is `Record<string, ComponentType<any>>` — every key is the\n * tag name an MDX file uses (`<CTASection ref=\"post-cta\" />` resolves\n * via the `CTASection` key). Values are React components the consumer\n * authored under their own `src/sections/blog.sections.tsx` and\n * wrapped in `<WebsiteSection sectionRef={…} category={…}>` so the\n * label-key context is established before the section's\n * `useWebsiteLabel(slot)` calls fire. The framework does NOT inspect\n * the shape — discipline lives in the consumer's section registry\n * + the label-pack validation boundary (which proves the locale pack covers\n * each section's expected keys).\n *\n * # Why a `ComponentType<any>` value type and not a stricter generic\n *\n * MDX components receive their own props (children, plus whatever the\n * MDX author writes inline as JSX attributes). The type system cannot\n * narrow this through the provider boundary because the MDX compiler\n * does the routing at compile time. `ComponentType<any>` is the\n * convention `@mdx-js/react` itself uses (`MDXComponents` in\n * `mdx/types.js`) — staying compatible with the upstream type avoids\n * a wrap/unwrap dance at every consumer call site.\n *\n * # Bundle boundary\n *\n * Ships into the React-island bundle (consumed transitively from\n * `BlogPost.tsx` which itself sits behind the consumer's per-page\n * bridge file). MUST stay clear of `node:*` and SSR-tier specifiers\n * — the bundle-isolation test walks `mdx.ts` as one of its entries.\n */\nexport interface WebsiteMdxComponentsMap {\n /**\n * Tag-name → component map. The MDX compiler resolves each\n * `<TagName />` in a blog post's body against this object.\n */\n readonly [tagName: string]: ComponentType<any>;\n}\n\nexport interface WebsiteMdxProviderProps {\n /**\n * Consumer-supplied component overrides. Keys are MDX tag names;\n * values are the React components those tags resolve to.\n */\n components: WebsiteMdxComponentsMap;\n /**\n * MDX subtree (typically the compiled `<MdxBody/>` from a content\n * collection entry). May render any number of provider-scoped\n * components.\n */\n children: ReactNode;\n}\n\nexport function WebsiteMdxProvider(props: WebsiteMdxProviderProps): ReactNode {\n const { components, children } = props;\n return <MDXProvider components={components}>{children}</MDXProvider>;\n}\nWebsiteMdxProvider.displayName = 'WebsiteMdxProvider';\n/** @wildo_source:part:end saas.website.blog.mdx-provider */\n"]}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Top-level barrel for the marketing-blog MDX adapter (Phase 7).
3
+ *
4
+ * # Why a dedicated subpath instead of folding into the root barrel
5
+ *
6
+ * `@wildo-ai/saas-website/mdx` ships into the React-island bundle
7
+ * (consumed transitively from a consumer's per-post `.astro` page
8
+ * which imports `<BlogPost>` and renders it client-side). The
9
+ * `@mdx-js/react` runtime adds non-trivial weight to the closure;
10
+ * isolating the entry behind a dedicated subpath:
11
+ *
12
+ * - keeps `index.ts` (the Node + React companion-runtime entry) free
13
+ * of MDX runtime dependencies for sites that ship landing-page-only
14
+ * marketing surfaces;
15
+ * - lets the bundle-isolation test walk this entry independently
16
+ * (see `engine/saas-website/src/__tests__/bundle-isolation.test.ts`
17
+ * `ENTRY_FILES` list) so an accidental `node:fs` import inside
18
+ * `BlogPost.tsx` regresses against the React-bundle constraint
19
+ * without polluting the other entries' allow-lists.
20
+ *
21
+ * Pattern mirrors `astro.ts` / `astro-island.ts` / `config-loader.ts`:
22
+ * one purpose, one barrel, one bundle-isolation entry.
23
+ */
24
+ export * from './mdx/index';
25
+ /**
26
+ * The blog adapter's per-locale bridge factory
27
+ * (`createWebsiteBlogPostBridgeIsland`). Lives in `astro/` beside
28
+ * `bridge-runtime.tsx` (same closure-over-deps pattern) but is exported
29
+ * from THIS entry — not `astro-island.ts` — because it hard-imports
30
+ * `./mdx/BlogPost`, whose `@mdx-js/react` peer is optional. Exporting it
31
+ * from the mandatory per-page bridge entry made the optional peer a
32
+ * de-facto install requirement for every non-blog site (Vite resolves the
33
+ * whole `export *` graph before tree-shaking). Here, only sites that opt
34
+ * into the blog adapter — and therefore install `@astrojs/mdx` +
35
+ * `@mdx-js/react` — ever resolve it.
36
+ */
37
+ export * from './astro/blog-post-bridge';
38
+ //# sourceMappingURL=mdx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdx.d.ts","sourceRoot":"","sources":["../../../src/mdx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,aAAa,CAAC;AAC5B;;;;;;;;;;;GAWG;AACH,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Top-level barrel for the marketing-blog MDX adapter (Phase 7).
3
+ *
4
+ * # Why a dedicated subpath instead of folding into the root barrel
5
+ *
6
+ * `@wildo-ai/saas-website/mdx` ships into the React-island bundle
7
+ * (consumed transitively from a consumer's per-post `.astro` page
8
+ * which imports `<BlogPost>` and renders it client-side). The
9
+ * `@mdx-js/react` runtime adds non-trivial weight to the closure;
10
+ * isolating the entry behind a dedicated subpath:
11
+ *
12
+ * - keeps `index.ts` (the Node + React companion-runtime entry) free
13
+ * of MDX runtime dependencies for sites that ship landing-page-only
14
+ * marketing surfaces;
15
+ * - lets the bundle-isolation test walk this entry independently
16
+ * (see `engine/saas-website/src/__tests__/bundle-isolation.test.ts`
17
+ * `ENTRY_FILES` list) so an accidental `node:fs` import inside
18
+ * `BlogPost.tsx` regresses against the React-bundle constraint
19
+ * without polluting the other entries' allow-lists.
20
+ *
21
+ * Pattern mirrors `astro.ts` / `astro-island.ts` / `config-loader.ts`:
22
+ * one purpose, one barrel, one bundle-isolation entry.
23
+ */
24
+ export * from './mdx/index.js';
25
+ /**
26
+ * The blog adapter's per-locale bridge factory
27
+ * (`createWebsiteBlogPostBridgeIsland`). Lives in `astro/` beside
28
+ * `bridge-runtime.tsx` (same closure-over-deps pattern) but is exported
29
+ * from THIS entry — not `astro-island.ts` — because it hard-imports
30
+ * `./mdx/BlogPost`, whose `@mdx-js/react` peer is optional. Exporting it
31
+ * from the mandatory per-page bridge entry made the optional peer a
32
+ * de-facto install requirement for every non-blog site (Vite resolves the
33
+ * whole `export *` graph before tree-shaking). Here, only sites that opt
34
+ * into the blog adapter — and therefore install `@astrojs/mdx` +
35
+ * `@mdx-js/react` — ever resolve it.
36
+ */
37
+ export * from './astro/blog-post-bridge.js';
38
+ //# sourceMappingURL=mdx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdx.js","sourceRoot":"","sources":["../../../src/mdx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,aAAa,CAAC;AAC5B;;;;;;;;;;;GAWG;AACH,cAAc,0BAA0B,CAAC","sourcesContent":["/**\n * Top-level barrel for the marketing-blog MDX adapter (Phase 7).\n *\n * # Why a dedicated subpath instead of folding into the root barrel\n *\n * `@wildo-ai/saas-website/mdx` ships into the React-island bundle\n * (consumed transitively from a consumer's per-post `.astro` page\n * which imports `<BlogPost>` and renders it client-side). The\n * `@mdx-js/react` runtime adds non-trivial weight to the closure;\n * isolating the entry behind a dedicated subpath:\n *\n * - keeps `index.ts` (the Node + React companion-runtime entry) free\n * of MDX runtime dependencies for sites that ship landing-page-only\n * marketing surfaces;\n * - lets the bundle-isolation test walk this entry independently\n * (see `engine/saas-website/src/__tests__/bundle-isolation.test.ts`\n * `ENTRY_FILES` list) so an accidental `node:fs` import inside\n * `BlogPost.tsx` regresses against the React-bundle constraint\n * without polluting the other entries' allow-lists.\n *\n * Pattern mirrors `astro.ts` / `astro-island.ts` / `config-loader.ts`:\n * one purpose, one barrel, one bundle-isolation entry.\n */\n\nexport * from './mdx/index';\n/**\n * The blog adapter's per-locale bridge factory\n * (`createWebsiteBlogPostBridgeIsland`). Lives in `astro/` beside\n * `bridge-runtime.tsx` (same closure-over-deps pattern) but is exported\n * from THIS entry — not `astro-island.ts` — because it hard-imports\n * `./mdx/BlogPost`, whose `@mdx-js/react` peer is optional. Exporting it\n * from the mandatory per-page bridge entry made the optional peer a\n * de-facto install requirement for every non-blog site (Vite resolves the\n * whole `export *` graph before tree-shaking). Here, only sites that opt\n * into the blog adapter — and therefore install `@astrojs/mdx` +\n * `@mdx-js/react` — ever resolve it.\n */\nexport * from './astro/blog-post-bridge';\n"]}
@@ -0,0 +1,75 @@
1
+ import { z } from 'zod';
2
+ import { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';
3
+ /**
4
+ * @wildo_source:part:start saas.website.blog.frontmatter facet:layer:shared facet:family:website
5
+ *
6
+ * `BlogPostFrontmatter` — the YAML frontmatter contract every blog
7
+ * post MDX file under `examples/<app>/website/src/content/blog/<locale>/`
8
+ * MUST satisfy.
9
+ *
10
+ * **Q16=B context**: blogs are authored as full per-locale MDX files
11
+ * (one MDX per (slug, locale) pair), NOT as label-pack-keyed content.
12
+ * The frontmatter therefore carries strings directly (`title`,
13
+ * `summary`) rather than label keys — there is no shared
14
+ * label-pack-driven authoring surface for blog content. This is
15
+ * intentional: blog copy is long-form and locale-divergent; forcing
16
+ * it through a structural label-pack would either inflate the pack
17
+ * or fragment the prose.
18
+ *
19
+ * **Field rationale**:
20
+ *
21
+ * - `title` — REQUIRED. Renders into `<title>`, `og:title`, and the
22
+ * in-page H1. Authored as a direct string, deliberately.
23
+ * - `summary` — REQUIRED. Renders into `<meta name="description">`,
24
+ * `og:description`, and listing-card descriptions. Direct string.
25
+ * - `slug` — REQUIRED. URL slug (lowercase kebab-case). Brand prevents
26
+ * accidental swap with `WebsitePageRef` (same shape, different role).
27
+ * - `locale` — REQUIRED. The post's locale. Drives the URL prefix
28
+ * (`/<locale>/blog/<slug>`) and `<html lang>`. Cross-locale
29
+ * correspondence is established by sharing the `slug` across
30
+ * per-locale MDX files (e.g. `en/why-context.md` and
31
+ * `fr/why-context.md` are the same post in two locales).
32
+ * - `publishedAt` — REQUIRED. ISO-8601 date-time string. Renders into
33
+ * `og:article:published_time` and the listing-card date label.
34
+ * Stored as string (not `z.coerce.date`) because YAML frontmatter
35
+ * parsers preserve the original string and the SEO emitters need
36
+ * the original ISO formatting (no Date.toISOString() round-trip
37
+ * loss).
38
+ * - `authorRef` — REQUIRED. Identifier of the author resolved by the
39
+ * consumer's author registry (typically a `src/content/authors/<ref>.ts`
40
+ * file). Brand keeps it distinct from page/section refs.
41
+ * - `tags` — REQUIRED, possibly empty. Lowercase kebab-case tag
42
+ * identifiers. Drives `og:article:tag` and the listing-page facets.
43
+ * - `coverImageUrl` — OPTIONAL. CDN URL for the blog post hero image
44
+ * and `og:image`.
45
+ *
46
+ * **Why a separate file from the page-manifest**: a blog post is NOT
47
+ * a `WebsitePageManifest` (no React `pageComponent` to mount — the
48
+ * MDX file IS the content). The Astro adapter emits one MDX route
49
+ * per post via `content collections`, with `BlogPostFrontmatter`
50
+ * driving the route generation and the SEO emission.
51
+ */
52
+ declare const _BlogPostSlugSchema: z.core.$ZodBranded<z.ZodString, "BlogPostSlug", "out">;
53
+ export declare const BlogPostSlugSchema: typeof _BlogPostSlugSchema;
54
+ export type BlogPostSlug = z.infer<typeof _BlogPostSlugSchema>;
55
+ declare const _BlogAuthorRefSchema: z.core.$ZodBranded<z.ZodString, "BlogAuthorRef", "out">;
56
+ export declare const BlogAuthorRefSchema: typeof _BlogAuthorRefSchema;
57
+ export type BlogAuthorRef = z.infer<typeof _BlogAuthorRefSchema>;
58
+ declare const _BlogPostTagSchema: z.core.$ZodBranded<z.ZodString, "BlogPostTag", "out">;
59
+ export declare const BlogPostTagSchema: typeof _BlogPostTagSchema;
60
+ export type BlogPostTag = z.infer<typeof _BlogPostTagSchema>;
61
+ declare const _BlogPostFrontmatterSchema: z.ZodObject<{
62
+ title: z.ZodString;
63
+ summary: z.ZodString;
64
+ slug: z.core.$ZodBranded<z.ZodString, "BlogPostSlug", "out">;
65
+ locale: z.ZodEnum<typeof AvailableLanguage>;
66
+ publishedAt: z.ZodISODateTime;
67
+ authorRef: z.core.$ZodBranded<z.ZodString, "BlogAuthorRef", "out">;
68
+ tags: z.ZodArray<z.core.$ZodBranded<z.ZodString, "BlogPostTag", "out">>;
69
+ coverImageUrl: z.ZodOptional<z.ZodURL>;
70
+ }, z.core.$strip>;
71
+ export declare const BlogPostFrontmatterSchema: typeof _BlogPostFrontmatterSchema;
72
+ export type BlogPostFrontmatter = z.infer<typeof _BlogPostFrontmatterSchema>;
73
+ export {};
74
+ /** @wildo_source:part:end saas.website.blog.frontmatter */
75
+ //# sourceMappingURL=blog-post-frontmatter.shared.schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blog-post-frontmatter.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../../src/schemas/blog/blog-post-frontmatter.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,QAAA,MAAM,mBAAmB,wDAQC,CAAC;AAE3B,eAAO,MAAM,kBAAkB,EAAE,OAAO,mBAAyC,CAAC;AAElF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAE/D,QAAA,MAAM,oBAAoB,yDAQC,CAAC;AAE5B,eAAO,MAAM,mBAAmB,EAAE,OAAO,oBAA2C,CAAC;AAErF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEjE,QAAA,MAAM,kBAAkB,uDAQC,CAAC;AAE1B,eAAO,MAAM,iBAAiB,EAAE,OAAO,kBAAuC,CAAC;AAE/E,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE7D,QAAA,MAAM,0BAA0B;;;;;;;;;iBAS9B,CAAC;AAEH,eAAO,MAAM,yBAAyB,EAAE,OAAO,0BACnB,CAAC;AAE7B,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;;AAC7E,2DAA2D"}