@wildo-ai/saas-website 1.1.3 → 1.1.4

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 (76) hide show
  1. package/dist/esm/astro/blog-post-bridge.d.ts.map +1 -1
  2. package/dist/esm/astro/blog-post-bridge.js.map +1 -1
  3. package/dist/esm/astro/blog-post-head.renderer.d.ts.map +1 -1
  4. package/dist/esm/astro/bridge-runtime.d.ts.map +1 -1
  5. package/dist/esm/astro/bridge-runtime.js.map +1 -1
  6. package/dist/esm/astro/collect-expected-label-keys.d.ts.map +1 -1
  7. package/dist/esm/astro/headers-renderer.d.ts.map +1 -1
  8. package/dist/esm/astro/i18n-routing.helper.d.ts.map +1 -1
  9. package/dist/esm/astro/label-pack-loader.d.ts.map +1 -1
  10. package/dist/esm/astro/llms-txt-server.d.ts.map +1 -1
  11. package/dist/esm/astro/pick-labels-for-page.d.ts.map +1 -1
  12. package/dist/esm/astro/robots-renderer.d.ts.map +1 -1
  13. package/dist/esm/astro/robots-renderer.js.map +1 -1
  14. package/dist/esm/astro/sitemap-coverage.d.ts.map +1 -1
  15. package/dist/esm/astro/structured-data.renderer.d.ts.map +1 -1
  16. package/dist/esm/astro/website-page-head.renderer.d.ts.map +1 -1
  17. package/dist/esm/astro/website-page-head.renderer.js.map +1 -1
  18. package/dist/esm/astro/website-page-runtime.helper.d.ts.map +1 -1
  19. package/dist/esm/astro/website-site-context.d.ts.map +1 -1
  20. package/dist/esm/astro-island.d.ts.map +1 -1
  21. package/dist/esm/astro.d.ts.map +1 -1
  22. package/dist/esm/companion-exports.d.ts.map +1 -1
  23. package/dist/esm/components/low-level/WebsiteInternalButton.d.ts.map +1 -1
  24. package/dist/esm/components/low-level/WebsiteInternalLink.d.ts.map +1 -1
  25. package/dist/esm/config/define-website-config.d.ts.map +1 -1
  26. package/dist/esm/config/index.d.ts.map +1 -1
  27. package/dist/esm/config/load-website-config.d.ts.map +1 -1
  28. package/dist/esm/config/wildo-website-config.schemas.d.ts.map +1 -1
  29. package/dist/esm/config/wildo-website-config.schemas.js.map +1 -1
  30. package/dist/esm/config-loader.d.ts.map +1 -1
  31. package/dist/esm/core/anonymous-session/InboundContactForm.d.ts.map +1 -1
  32. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts.map +1 -1
  33. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js.map +1 -1
  34. package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts.map +1 -1
  35. package/dist/esm/core/contexts/WebsitePageContext.d.ts.map +1 -1
  36. package/dist/esm/core/contexts/WebsitePageContext.js.map +1 -1
  37. package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts.map +1 -1
  38. package/dist/esm/core/contexts/WebsiteRuntimeContext.js.map +1 -1
  39. package/dist/esm/core/contexts/WebsiteSectionContext.d.ts.map +1 -1
  40. package/dist/esm/core/contexts/WebsiteSectionContext.js.map +1 -1
  41. package/dist/esm/core/contexts/useWebsitePage.d.ts.map +1 -1
  42. package/dist/esm/core/contexts/useWebsiteRuntime.d.ts.map +1 -1
  43. package/dist/esm/core/contexts/useWebsiteSection.d.ts.map +1 -1
  44. package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts.map +1 -1
  45. package/dist/esm/core/external-providers/frontend-provider-registry.website.js.map +1 -1
  46. package/dist/esm/core/external-providers/provider-scripts.website.d.ts.map +1 -1
  47. package/dist/esm/core/external-providers/provider-scripts.website.js.map +1 -1
  48. package/dist/esm/core/external-providers/useWebsiteProviderScripts.d.ts.map +1 -1
  49. package/dist/esm/core/external-providers/useWebsiteProviderScripts.js.map +1 -1
  50. package/dist/esm/core/factories/define-website-page-manifest.d.ts.map +1 -1
  51. package/dist/esm/core/factories/define-website-section.d.ts.map +1 -1
  52. package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts.map +1 -1
  53. package/dist/esm/core/hooks/useWebsiteLabel.d.ts.map +1 -1
  54. package/dist/esm/core/layouts/WebsitePageLayout.d.ts.map +1 -1
  55. package/dist/esm/core/layouts/WebsitePageLayout.js.map +1 -1
  56. package/dist/esm/core/layouts/WebsiteSection.d.ts.map +1 -1
  57. package/dist/esm/core/routing/internal-routing.utils.d.ts.map +1 -1
  58. package/dist/esm/index.d.ts.map +1 -1
  59. package/dist/esm/mdx/BlogPost.d.ts.map +1 -1
  60. package/dist/esm/mdx/blog-post-collection.config.d.ts.map +1 -1
  61. package/dist/esm/mdx/blog-post-frontmatter-source.d.ts.map +1 -1
  62. package/dist/esm/mdx/index.d.ts.map +1 -1
  63. package/dist/esm/mdx.d.ts.map +1 -1
  64. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts.map +1 -1
  65. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts.map +1 -1
  66. package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts.map +1 -1
  67. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts.map +1 -1
  68. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts.map +1 -1
  69. package/dist/esm/schemas/refs/page-ref.schemas.d.ts.map +1 -1
  70. package/dist/esm/schemas/refs/section-ref.schemas.d.ts.map +1 -1
  71. package/dist/esm/schemas/sections/website-section-category.shared.d.ts.map +1 -1
  72. package/dist/esm/schemas/sections/website-section-category.shared.js.map +1 -1
  73. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts.map +1 -1
  74. package/dist/esm/schemas/validators/label-pack.validator.d.ts.map +1 -1
  75. package/dist/tsconfig.build.tsbuildinfo +1 -1
  76. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"blog-post-bridge.d.ts","sourceRoot":"","sources":["../../../../src/astro/blog-post-bridge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAa,MAAM,OAAO,CAAC;AAEzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAO9E,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,+DAA+D,CAAC;AACrH,OAAO,EAAY,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+DAA+D,CAAC;AACzG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC;AACvG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuMG;AAEH;;;GAGG;AACH,MAAM,WAAW,qCAAqC;IACpD;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5D;;;;;OAKG;IACH,UAAU,EAAE,uBAAuB,CAAC;IACpC;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,uBAAuB,CAAC;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;OAIG;IACH,aAAa,EAAE,iBAAiB,CAAC;IACjC,2DAA2D;IAC3D,SAAS,EAAE,SAAS,CAAC;IACrB,iEAAiE;IACjE,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;;OAKG;IACH,yBAAyB,EAAE,eAAe,CAAC;IAC3C,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAC3C;;;;;;;;;;;;;;;;;;OAkBG;IACH,uBAAuB,CAAC,EAAE,+BAA+B,CAAC;CAC3D;AAID;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,qCAAqC,GAC1C,iBAAiB,CAAC,gCAAgC,CAAC,CAqErD;AAED;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAC9B,sDAAsD"}
1
+ {"version":3,"file":"blog-post-bridge.d.ts","sourceRoot":"","sources":["../../../src/astro/blog-post-bridge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAa,MAAM,OAAO,CAAC;AAEzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAO9E,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,+DAA+D,CAAC;AACrH,OAAO,EAAY,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+DAA+D,CAAC;AACzG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC;AACvG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuMG;AAEH;;;GAGG;AACH,MAAM,WAAW,qCAAqC;IACpD;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5D;;;;;OAKG;IACH,UAAU,EAAE,uBAAuB,CAAC;IACpC;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,uBAAuB,CAAC;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;OAIG;IACH,aAAa,EAAE,iBAAiB,CAAC;IACjC,2DAA2D;IAC3D,SAAS,EAAE,SAAS,CAAC;IACrB,iEAAiE;IACjE,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;;OAKG;IACH,yBAAyB,EAAE,eAAe,CAAC;IAC3C,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAC3C;;;;;;;;;;;;;;;;;;OAkBG;IACH,uBAAuB,CAAC,EAAE,+BAA+B,CAAC;CAC3D;AAID;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,qCAAqC,GAC1C,iBAAiB,CAAC,gCAAgC,CAAC,CAqErD;AAED;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAC9B,sDAAsD"}
@@ -1 +1 @@
1
- {"version":3,"file":"blog-post-bridge.js","sourceRoot":"","sources":["../../../../src/astro/blog-post-bridge.tsx"],"names":[],"mappings":";AAKA,OAAO,EACL,6BAA6B,GAE9B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,qCAAqC,EAAE,MAAM,+DAA+D,CAAC;AAEtH,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAuU/D,MAAM,oBAAoB,GAA4B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAExE;;;;;;GAMG;AACH,MAAM,UAAU,iCAAiC,CAC/C,IAA2C;IAE3C,MAAM,EACJ,aAAa,EACb,UAAU,EACV,aAAa,GAAG,oBAAoB,GACrC,GAAG,IAAI,CAAC;IAET,SAAS,2BAA2B,CAAC,EACnC,IAAI,EACJ,cAAc,EACd,MAAM,EACN,MAAM,EACN,aAAa,EACb,SAAS,EACT,YAAY,EACZ,yBAAyB,EACzB,iBAAiB,EACjB,uBAAuB,GACU;QACjC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B;;;;;;;eAOG;YACH,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC7C,MAAM,KAAK,GACT,SAAS,CAAC,MAAM,IAAI,CAAC;gBACnB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;gBACtB,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,SAAS,CAAC,MAAM,SAAS,CAAC;YAC3E,MAAM,IAAI,KAAK,CACb,uDAAuD,IAAI,KAAK;gBAC9D,sDAAsD,KAAK,IAAI;gBAC/D,2EAA2E;gBAC3E,yCAAyC,CAC5C,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAA+B;YAC/C,MAAM;YACN,aAAa;YACb,SAAS;YACT,YAAY;YACZ,UAAU;YACV,yBAAyB;YACzB,wBAAwB,EAAE,qCAAqC,CAAC;gBAC9D,OAAO,EAAE,iBAAiB;gBAC1B,OAAO,EAAE,uBAAuB;aACjC,CAAC;SACH,CAAC;QACF,OAAO,CACL,KAAC,6BAA6B,IAAC,KAAK,EAAE,YAAY,YAChD,KAAC,QAAQ,IACP,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,YAE5B,KAAC,OAAO,KAAG,GACF,GACmB,CACjC,CAAC;IACJ,CAAC;IACD,2BAA2B,CAAC,WAAW,GAAG,6BAA6B,CAAC;IAExE,OAAO,2BAA2B,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAAE,CAAC","sourcesContent":["import type { ComponentType, FunctionComponent, ReactNode } from 'react';\n\nimport type { FrontendProvidersBlock } from '@wildo-ai/saas-models/public-runtime';\nimport type { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';\n\nimport {\n WebsiteRuntimeContextProvider,\n type WebsiteRuntimeContextValue,\n} from '../core/contexts/WebsiteRuntimeContext';\nimport { createFrontendWebsiteProviderRegistry } from '../core/external-providers/frontend-provider-registry.website';\nimport type { GeneratedWebsiteProviderModules } from '../core/external-providers/frontend-provider-registry.website';\nimport { BlogPost, BLOG_POST_PAGE_REF } from '../mdx/BlogPost';\nimport type { WebsiteMdxComponentsMap } from '../mdx/website-mdx-provider';\nimport type { WebsiteDesignTokens } from '../schemas/design-tokens/website-design-tokens.shared.schemas';\nimport type { WebsiteLabelKey } from '../schemas/label-keys/website-label-key.schemas';\nimport type { WebsiteNavigationConfig } from '../schemas/manifests/website-root-config.shared.schemas';\nimport type { LabelPack } from '../schemas/validators/label-pack.validator';\n\n/**\n * @wildo_source:part:start saas.website.blog.bridge facet:layer:astro facet:family:website\n *\n * `createWebsiteBlogPostBridgeIsland(deps)` — factory that returns the\n * React island a consumer's per-locale `*.bridge.tsx` module exports for\n * mounting blog post pages. **Sibling** of `createWebsitePageBridgeIsland`\n * but adapted to the dynamic-routing constraint of the marketing-blog\n * adapter (Phase 7, D-6 = Option A).\n *\n * # Why blog posts cannot reuse the page bridge factory\n *\n * Three structural differences between marketing pages and blog posts\n * forced this dedicated factory shape:\n *\n * 1. **Per-slug body resolution.** A marketing page (`landing`,\n * `pricing`, etc.) has ONE `PageComponent` known at bridge-module\n * load time — the page bridge closes over it. A blog post's body\n * is the compiled MDX module, which varies per slug. Closing the\n * MDX body inside the factory at module load time would force one\n * bridge file per post (defeats Q16=B \"one MDX file per post\").\n * Instead, the factory closes over a `slugToMdxBody: Record<string,\n * ComponentType>` map — typically built from\n * `import.meta.glob('./content/blog/<locale>/*.mdx', { eager: true })`\n * on the consumer side — and the island accepts the active `slug`\n * as a primitive (JSON-serializable) prop.\n *\n * 2. **Layout already wrapped by `<BlogPost>`.** The page bridge wraps\n * its `PageComponent` in `<WebsitePageLayout pageRef={…}>`. The\n * `<BlogPost>` renderer ALREADY wraps its tree in\n * `<WebsitePageLayout pageRef={BLOG_POST_PAGE_REF}>` (the framework\n * reserves the page ref for the entire blog surface — see\n * `BLOG_POST_PAGE_REF` JSDoc in `BlogPost.tsx`). Reusing the page\n * bridge would double-wrap the layout. This factory instead\n * provides the runtime context and yields directly to `<BlogPost>`,\n * which owns the layout boundary itself.\n *\n * 3. **Astro's React-children context-propagation gap.** Astro\n * renders React component children INDEPENDENTLY of the parent\n * component when the boundary is `.astro` ↔ `.tsx`, even on the\n * server side. This means\n * `<BlogPost client:load><Content /></BlogPost>` written in an\n * `.astro` file would NOT propagate the `<WebsiteMdxProvider>`\n * context to the React components embedded inside `<Content />`\n * (the embedded `<CTASection />` would render WITHOUT the engine's\n * MDX provider scope; the `mdxComponents` map would be ignored).\n * Confirmed via the Astro docs, `@astrojs/react` integration\n * readme, and the documented \"Bridging two JSX runtimes\" gotcha.\n *\n * The fix: the entire blog post tree (BlogPost + MDX body +\n * embedded section components) lives inside ONE React island. The\n * MDX module is imported as a React component via Astro's\n * `import.meta.glob`, and the bridge renders it as JSX children\n * of `<BlogPost>` from INSIDE the island — no `.astro` ↔ `.tsx`\n * boundary is crossed during the body render.\n *\n * # Why hydration is required (vs. pure SSR)\n *\n * The `WebsiteRuntimeContextProvider` + `<BlogPost>` tree could in\n * theory render on the server only (no `client:*` directive). But:\n *\n * - Embedded sections (`<CTASection />`) typically have their own\n * interactivity (analytics handlers, A/B variant flippers, etc.)\n * that need React event listeners to attach client-side.\n * - The framework's `useWebsiteLabel(...)` hook chain assumes a live\n * React render tree — a pure-SSR tree would freeze label resolution\n * at build time, but any future client-driven label override (e.g.\n * a debug-mode label inspector) would silently break.\n *\n * The factory therefore returns an island that the consumer's `.astro`\n * mounts with `client:load` (or `client:idle` for posts known to be\n * non-interactive). The hydration cost is bounded by the per-locale MDX\n * glob — see \"Bundle scaling cliff\" below.\n *\n * # Bundle scaling cliff (deferred trade-off)\n *\n * `import.meta.glob({ eager: true })` materializes EVERY post's\n * compiled JS into the per-locale React-island bundle (~5–20 KB per\n * post depending on length and embedded section count). For the\n * Phase 7 dogfood (≤10 posts) this is fine and matches the documented\n * Astro+MDX pattern. Past ~50 posts this becomes a real budget concern.\n * The factory's API is forward-compatible with `{ eager: false }`\n * (lazy loaders): swap the consumer's glob to lazy mode and the\n * `slugToMdxBody[slug]` lookup returns a `() => Promise<{ default:\n * ComponentType }>`; wrap in `React.lazy()` + `<Suspense>` and the\n * factory call site stays unchanged. The migration is a consumer-side\n * change, not an engine API break.\n *\n * # Authoring pattern\n *\n * **Per-locale bridge file** (consumer side, ONE per locale):\n *\n * ```tsx\n * // examples/<app>/website/src/pages-impl/blog-post-en.bridge.tsx\n * import type { ComponentType } from 'react';\n *\n * import { createWebsiteBlogPostBridgeIsland }\n * from '@wildo-ai/saas-website/mdx';\n * import { BLOG_POST_MDX_COMPONENTS }\n * from './blog-post.mdx-components';\n * import { WEBSITE_ROOT_CONFIG } from '../website-root.config';\n *\n * // Static analyzable glob — Vite resolves at build time. The glob\n * // pattern MUST be a single string literal (no concatenation, no\n * // variable interpolation); Vite parses it AST-side. The `as` cast\n * // narrows the unknown record to the per-MDX-file shape Astro's mdx\n * // integration emits (default export = the compiled React component).\n * const rawModules = import.meta.glob('./content/blog/en/*.mdx', {\n * eager: true,\n * }) as Record<string, { default: ComponentType }>;\n *\n * const slugToMdxBody: Record<string, ComponentType> = {};\n * for (const [path, mod] of Object.entries(rawModules)) {\n * // './content/blog/en/why-context.mdx' -> 'why-context'\n * const slug = path.split('/').pop()!.replace(/\\.mdx$/, '');\n * slugToMdxBody[slug] = mod.default;\n * }\n *\n * export const BlogPostEnBridgeIsland =\n * createWebsiteBlogPostBridgeIsland({\n * slugToMdxBody,\n * navigation: WEBSITE_ROOT_CONFIG.navigation,\n * mdxComponents: BLOG_POST_MDX_COMPONENTS,\n * });\n * ```\n *\n * **Per-locale `[slug].astro` shell** (consumer side):\n *\n * ```astro\n * ---\n * import { getCollection } from 'astro:content';\n * import {\n * loadWebsitePageRuntime,\n * renderBlogPostHeadHtml,\n * renderWebsiteDesignTokensCss,\n * } from '@wildo-ai/saas-website/astro';\n * import { parseBlogPostFrontmatter } from '@wildo-ai/saas-website/mdx';\n * import { BlogPostEnBridgeIsland } from '@/pages-impl/blog-post-en.bridge';\n * import { BLOG_POST_PAGE_MANIFEST } from '@/pages-impl/blog-post.page';\n * import { WEBSITE_SITE_CONTEXT } from '@/website-site-context';\n *\n * export async function getStaticPaths() {\n * const posts = await getCollection('blog');\n * const defaultLocale = WEBSITE_SITE_CONTEXT.websiteConfig.defaultLocale;\n * return posts\n * .filter((p) => p.data.locale === defaultLocale)\n * .map((p) => ({ params: { slug: p.data.slug }, props: { entry: p } }));\n * }\n * const { entry } = Astro.props;\n *\n * const runtime = loadWebsitePageRuntime({\n * manifest: BLOG_POST_PAGE_MANIFEST,\n * siteContext: WEBSITE_SITE_CONTEXT,\n * labelPacksDir: './src/i18n',\n * astroLocale: Astro.currentLocale,\n * });\n * const frontmatter = parseBlogPostFrontmatter(entry.data, { source: entry.id });\n * const headHtml = renderBlogPostHeadHtml({\n * siteContext: WEBSITE_SITE_CONTEXT,\n * locale: runtime.locale,\n * routePath: `/blog/${frontmatter.slug}`,\n * frontmatter,\n * });\n * const designTokensCss = renderWebsiteDesignTokensCss(\n * WEBSITE_SITE_CONTEXT.rootConfig.designTokens,\n * );\n * ---\n * <!doctype html>\n * <html lang={runtime.locale}>\n * <head>\n * <meta charset=\"UTF-8\" />\n * <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n * <Fragment set:html={headHtml} />\n * <style set:html={designTokensCss}></style>\n * </head>\n * <body>\n * <BlogPostEnBridgeIsland\n * client:load\n * slug={frontmatter.slug}\n * rawFrontmatter={entry.data}\n * source={entry.id}\n * locale={runtime.locale}\n * defaultLocale={runtime.defaultLocale}\n * labelPack={runtime.labelPack}\n * designTokens={WEBSITE_SITE_CONTEXT.rootConfig.designTokens}\n * skipToMainContentLabelKey={\n * WEBSITE_SITE_CONTEXT.rootConfig.skipToMainContentLabelKey\n * }\n * />\n * </body>\n * </html>\n * ```\n *\n * # Boundary\n *\n * Strictly client-bundle-safe (re-exported from `mdx.ts` — NOT from\n * `astro-island.ts`, because this module hard-imports the MDX adapter\n * whose `@mdx-js/react` peer is optional; walked by the\n * bundle-isolation test). MUST stay clear of `node:*` and SSR-tier\n * specifiers.\n */\n\n/**\n * Module-load-time dependencies — closed over inside the returned\n * island. NEVER cross the hydration boundary as serialized props.\n */\nexport interface CreateWebsiteBlogPostBridgeIslandDeps {\n /**\n * Per-slug map of compiled MDX bodies (each entry is a React\n * component — the `.default` export of the MDX module). Typically\n * built from `import.meta.glob('./content/blog/<locale>/*.mdx',\n * { eager: true })` with the path-key normalized to the slug. Closed\n * over at module-load time so the entire MDX body graph for the\n * locale lands inside ONE React island bundle (D-6 Option A) — this\n * is the structural fix for Astro's React-children context-propagation\n * gap (see file preamble).\n *\n * The map is read by `slugToMdxBody[props.slug]` at island render\n * time. A missing slug throws a clear framework-owned error (rather than\n * rendering an empty body silently); the consumer's `getStaticPaths`\n * is responsible for not emitting routes for slugs absent from the\n * map.\n *\n * **Why `ComponentType<any>` and not a stricter generic**: matches\n * the upstream `@mdx-js/react` convention (`MDXContent` from\n * `mdx/types` is parameterized over an open `MDXProps` shape). MDX\n * compilation hands the body a compiler-managed props object that\n * the type system cannot narrow at the framework boundary; using\n * `<any>` here keeps the consumer's\n * `import.meta.glob(...) as Record<string, { default: ComponentType }>`\n * cast assignable without an additional wrap/unwrap. Same posture\n * as `WebsiteMdxComponentsMap` (intentional symmetry).\n */\n slugToMdxBody: Readonly<Record<string, ComponentType<any>>>;\n /**\n * Site-wide navigation slot bindings (header / footer components).\n * Closed over here for the same reason as the page bridge: both\n * fields are `ComponentType` refs that cannot survive Astro's\n * serialization boundary.\n */\n navigation: WebsiteNavigationConfig;\n /**\n * MDX-tag → React-component map forwarded into `<BlogPost>` and\n * scoped via `<WebsiteMdxProvider>`. Typically a small object\n * literal exporting the consumer-authored business sections that\n * blog posts can embed (`<CTASection />`, etc.). Closed over here\n * (rather than passed as an island prop) because the values are\n * `ComponentType` refs.\n */\n mdxComponents?: WebsiteMdxComponentsMap;\n}\n\n/**\n * Hydration-boundary props — what the consumer's `.astro` page passes\n * to `<BlogPostEnBridgeIsland client:load ...{primitiveProps}/>`.\n * Every field is JSON-serializable.\n */\nexport interface WebsiteBlogPostBridgeIslandProps {\n /**\n * Slug of the post being rendered. Used by the island to look up\n * the matching MDX body in `deps.slugToMdxBody`. Carried as a plain\n * string (not the branded `BlogPostSlug`) because Astro's\n * serialization boundary unwraps brands.\n */\n slug: string;\n /**\n * Raw frontmatter object Astro hands the page from `entry.data`.\n * Forwarded straight to `<BlogPost>` for strict Zod-4 validation.\n * The bridge does NOT re-validate (single validation surface, owned\n * by the renderer).\n */\n rawFrontmatter: unknown;\n /**\n * Diagnostic source identifier echoed into validation errors —\n * typically `entry.id` from Astro's content collection. Optional\n * but recommended for actionable error messages.\n */\n source?: string;\n /** The locale Astro resolved (with default-locale fallback). */\n locale: AvailableLanguage;\n /**\n * The site's default locale. Required for `WebsiteInternalLink`\n * locale-prefix logic (mirrors the page bridge's `defaultLocale`\n * island prop).\n */\n defaultLocale: AvailableLanguage;\n /** Already-loaded + already-shape-validated label pack. */\n labelPack: LabelPack;\n /** Design-token bundle from `WebsiteRootConfig.designTokens`. */\n designTokens: WebsiteDesignTokens;\n /**\n * Fully-composed label key the framework reads to render the\n * \"Skip to main content\" affordance. Mirrors\n * `WebsiteRootConfig.skipToMainContentLabelKey`. Carried as a\n * primitive island prop for the same reason as the page bridge.\n */\n skipToMainContentLabelKey: WebsiteLabelKey;\n /** Optional website-facing public providers materialized at build time. */\n frontendProviders?: FrontendProvidersBlock;\n /**\n * The CODE channel for those providers (#332): the\n * `generatedFrontendProviderModules` export of this website service's own\n * `src/generated/frontend-providers.generated.ts`, written by\n * `wildo config sync`.\n *\n * `frontendProviders` above says WHICH providers this service turned on, in\n * this environment; this says what code the bundle actually contains for\n * them. Both are needed, because a JSON payload cannot carry an SDK loader\n * and a bundle cannot know which environment it is running in.\n *\n * NOT a JSON-serializable island prop like its siblings, and it does not need\n * to be: the bridge module is bundled with the page, so the generated module\n * map is an ordinary import in the same graph rather than something that has\n * to cross the hydration boundary.\n *\n * Omitted is the ordinary case for a website declaring no package-shipped\n * provider: no such file is generated, so there is nothing to import.\n */\n frontendProviderModules?: GeneratedWebsiteProviderModules;\n}\n\nconst EMPTY_MDX_COMPONENTS: WebsiteMdxComponentsMap = Object.freeze({});\n\n/**\n * Returns a FUNCTION component, not the wider `ComponentType` union. The island IS a function\n * component — Astro hydrates nothing else here — and the union is not callable, so declaring it\n * cost callers the ability to invoke the island directly (which the bridge suites do, to observe\n * the synchronous throw for an unregistered slug without routing it through React's reconciler\n * error path). `FunctionComponent` is assignable to `ComponentType`, so no consumer narrows.\n */\nexport function createWebsiteBlogPostBridgeIsland(\n deps: CreateWebsiteBlogPostBridgeIslandDeps,\n): FunctionComponent<WebsiteBlogPostBridgeIslandProps> {\n const {\n slugToMdxBody,\n navigation,\n mdxComponents = EMPTY_MDX_COMPONENTS,\n } = deps;\n\n function WebsiteBlogPostBridgeIsland({\n slug,\n rawFrontmatter,\n source,\n locale,\n defaultLocale,\n labelPack,\n designTokens,\n skipToMainContentLabelKey,\n frontendProviders,\n frontendProviderModules,\n }: WebsiteBlogPostBridgeIslandProps): ReactNode {\n const MdxBody = slugToMdxBody[slug];\n if (MdxBody === undefined) {\n /**\n * Loud failure — the consumer's `getStaticPaths` is supposed to\n * only emit routes for slugs present in the MDX glob. A missing\n * lookup means the glob and the collection are out of sync; the\n * operator needs an actionable error string with the offending\n * slug + the keys that ARE present (truncated to keep the build\n * log readable).\n */\n const knownKeys = Object.keys(slugToMdxBody);\n const known =\n knownKeys.length <= 5\n ? knownKeys.join(', ')\n : `${knownKeys.slice(0, 5).join(', ')}, … (${knownKeys.length} total)`;\n throw new Error(\n `[blog-post-bridge] No MDX body registered for slug=\"${slug}\". ` +\n `The bridge factory's slugToMdxBody map only knows: ${known}. ` +\n `Verify the consumer's import.meta.glob('...content/blog/<locale>/*.mdx') ` +\n `pattern matches the source file naming.`,\n );\n }\n\n const runtimeValue: WebsiteRuntimeContextValue = {\n locale,\n defaultLocale,\n labelPack,\n designTokens,\n navigation,\n skipToMainContentLabelKey,\n frontendProviderRegistry: createFrontendWebsiteProviderRegistry({\n entries: frontendProviders,\n modules: frontendProviderModules,\n }),\n };\n return (\n <WebsiteRuntimeContextProvider value={runtimeValue}>\n <BlogPost\n rawFrontmatter={rawFrontmatter}\n source={source}\n mdxComponents={mdxComponents}\n >\n <MdxBody />\n </BlogPost>\n </WebsiteRuntimeContextProvider>\n );\n }\n WebsiteBlogPostBridgeIsland.displayName = 'WebsiteBlogPostBridgeIsland';\n\n return WebsiteBlogPostBridgeIsland;\n}\n\n/**\n * Re-export of the framework-reserved blog-post page ref. Consumers\n * authoring `BLOG_POST_PAGE_MANIFEST` need this constant to satisfy\n * the manifest's `ref` field; re-exporting it from the bridge module\n * means the consumer's per-locale bridge file can grab both symbols\n * from the one `@wildo-ai/saas-website/mdx` import it already has.\n */\nexport { BLOG_POST_PAGE_REF };\n/** @wildo_source:part:end saas.website.blog.bridge */\n"]}
1
+ {"version":3,"file":"blog-post-bridge.js","sourceRoot":"","sources":["../../../src/astro/blog-post-bridge.tsx"],"names":[],"mappings":";AAKA,OAAO,EACL,6BAA6B,GAE9B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,qCAAqC,EAAE,MAAM,+DAA+D,CAAC;AAEtH,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAuU/D,MAAM,oBAAoB,GAA4B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAExE;;;;;;GAMG;AACH,MAAM,UAAU,iCAAiC,CAC/C,IAA2C;IAE3C,MAAM,EACJ,aAAa,EACb,UAAU,EACV,aAAa,GAAG,oBAAoB,GACrC,GAAG,IAAI,CAAC;IAET,SAAS,2BAA2B,CAAC,EACnC,IAAI,EACJ,cAAc,EACd,MAAM,EACN,MAAM,EACN,aAAa,EACb,SAAS,EACT,YAAY,EACZ,yBAAyB,EACzB,iBAAiB,EACjB,uBAAuB,GACU;QACjC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B;;;;;;;eAOG;YACH,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC7C,MAAM,KAAK,GACT,SAAS,CAAC,MAAM,IAAI,CAAC;gBACnB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;gBACtB,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,SAAS,CAAC,MAAM,SAAS,CAAC;YAC3E,MAAM,IAAI,KAAK,CACb,uDAAuD,IAAI,KAAK;gBAC9D,sDAAsD,KAAK,IAAI;gBAC/D,2EAA2E;gBAC3E,yCAAyC,CAC5C,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAA+B;YAC/C,MAAM;YACN,aAAa;YACb,SAAS;YACT,YAAY;YACZ,UAAU;YACV,yBAAyB;YACzB,wBAAwB,EAAE,qCAAqC,CAAC;gBAC9D,OAAO,EAAE,iBAAiB;gBAC1B,OAAO,EAAE,uBAAuB;aACjC,CAAC;SACH,CAAC;QACF,OAAO,CACL,KAAC,6BAA6B,IAAC,KAAK,EAAE,YAAY,YAChD,KAAC,QAAQ,IACP,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,YAE5B,KAAC,OAAO,KAAG,GACF,GACmB,CACjC,CAAC;IACJ,CAAC;IACD,2BAA2B,CAAC,WAAW,GAAG,6BAA6B,CAAC;IAExE,OAAO,2BAA2B,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAAE,CAAC","sourcesContent":["import type { ComponentType, FunctionComponent, ReactNode } from 'react';\n\nimport type { FrontendProvidersBlock } from '@wildo-ai/saas-models/public-runtime';\nimport type { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';\n\nimport {\n WebsiteRuntimeContextProvider,\n type WebsiteRuntimeContextValue,\n} from '../core/contexts/WebsiteRuntimeContext';\nimport { createFrontendWebsiteProviderRegistry } from '../core/external-providers/frontend-provider-registry.website';\nimport type { GeneratedWebsiteProviderModules } from '../core/external-providers/frontend-provider-registry.website';\nimport { BlogPost, BLOG_POST_PAGE_REF } from '../mdx/BlogPost';\nimport type { WebsiteMdxComponentsMap } from '../mdx/website-mdx-provider';\nimport type { WebsiteDesignTokens } from '../schemas/design-tokens/website-design-tokens.shared.schemas';\nimport type { WebsiteLabelKey } from '../schemas/label-keys/website-label-key.schemas';\nimport type { WebsiteNavigationConfig } from '../schemas/manifests/website-root-config.shared.schemas';\nimport type { LabelPack } from '../schemas/validators/label-pack.validator';\n\n/**\n * @wildo_source:part:start saas.website.blog.bridge facet:layer:astro facet:family:website\n *\n * `createWebsiteBlogPostBridgeIsland(deps)` — factory that returns the\n * React island a consumer's per-locale `*.bridge.tsx` module exports for\n * mounting blog post pages. **Sibling** of `createWebsitePageBridgeIsland`\n * but adapted to the dynamic-routing constraint of the marketing-blog\n * adapter (Phase 7, D-6 = Option A).\n *\n * # Why blog posts cannot reuse the page bridge factory\n *\n * Three structural differences between marketing pages and blog posts\n * forced this dedicated factory shape:\n *\n * 1. **Per-slug body resolution.** A marketing page (`landing`,\n * `pricing`, etc.) has ONE `PageComponent` known at bridge-module\n * load time — the page bridge closes over it. A blog post's body\n * is the compiled MDX module, which varies per slug. Closing the\n * MDX body inside the factory at module load time would force one\n * bridge file per post (defeats Q16=B \"one MDX file per post\").\n * Instead, the factory closes over a `slugToMdxBody: Record<string,\n * ComponentType>` map — typically built from\n * `import.meta.glob('./content/blog/<locale>/*.mdx', { eager: true })`\n * on the consumer side — and the island accepts the active `slug`\n * as a primitive (JSON-serializable) prop.\n *\n * 2. **Layout already wrapped by `<BlogPost>`.** The page bridge wraps\n * its `PageComponent` in `<WebsitePageLayout pageRef={…}>`. The\n * `<BlogPost>` renderer ALREADY wraps its tree in\n * `<WebsitePageLayout pageRef={BLOG_POST_PAGE_REF}>` (the framework\n * reserves the page ref for the entire blog surface — see\n * `BLOG_POST_PAGE_REF` JSDoc in `BlogPost.tsx`). Reusing the page\n * bridge would double-wrap the layout. This factory instead\n * provides the runtime context and yields directly to `<BlogPost>`,\n * which owns the layout boundary itself.\n *\n * 3. **Astro's React-children context-propagation gap.** Astro\n * renders React component children INDEPENDENTLY of the parent\n * component when the boundary is `.astro` ↔ `.tsx`, even on the\n * server side. This means\n * `<BlogPost client:load><Content /></BlogPost>` written in an\n * `.astro` file would NOT propagate the `<WebsiteMdxProvider>`\n * context to the React components embedded inside `<Content />`\n * (the embedded `<CTASection />` would render WITHOUT the engine's\n * MDX provider scope; the `mdxComponents` map would be ignored).\n * Confirmed via the Astro docs, `@astrojs/react` integration\n * readme, and the documented \"Bridging two JSX runtimes\" gotcha.\n *\n * The fix: the entire blog post tree (BlogPost + MDX body +\n * embedded section components) lives inside ONE React island. The\n * MDX module is imported as a React component via Astro's\n * `import.meta.glob`, and the bridge renders it as JSX children\n * of `<BlogPost>` from INSIDE the island — no `.astro` ↔ `.tsx`\n * boundary is crossed during the body render.\n *\n * # Why hydration is required (vs. pure SSR)\n *\n * The `WebsiteRuntimeContextProvider` + `<BlogPost>` tree could in\n * theory render on the server only (no `client:*` directive). But:\n *\n * - Embedded sections (`<CTASection />`) typically have their own\n * interactivity (analytics handlers, A/B variant flippers, etc.)\n * that need React event listeners to attach client-side.\n * - The framework's `useWebsiteLabel(...)` hook chain assumes a live\n * React render tree — a pure-SSR tree would freeze label resolution\n * at build time, but any future client-driven label override (e.g.\n * a debug-mode label inspector) would silently break.\n *\n * The factory therefore returns an island that the consumer's `.astro`\n * mounts with `client:load` (or `client:idle` for posts known to be\n * non-interactive). The hydration cost is bounded by the per-locale MDX\n * glob — see \"Bundle scaling cliff\" below.\n *\n * # Bundle scaling cliff (deferred trade-off)\n *\n * `import.meta.glob({ eager: true })` materializes EVERY post's\n * compiled JS into the per-locale React-island bundle (~5–20 KB per\n * post depending on length and embedded section count). For the\n * Phase 7 dogfood (≤10 posts) this is fine and matches the documented\n * Astro+MDX pattern. Past ~50 posts this becomes a real budget concern.\n * The factory's API is forward-compatible with `{ eager: false }`\n * (lazy loaders): swap the consumer's glob to lazy mode and the\n * `slugToMdxBody[slug]` lookup returns a `() => Promise<{ default:\n * ComponentType }>`; wrap in `React.lazy()` + `<Suspense>` and the\n * factory call site stays unchanged. The migration is a consumer-side\n * change, not an engine API break.\n *\n * # Authoring pattern\n *\n * **Per-locale bridge file** (consumer side, ONE per locale):\n *\n * ```tsx\n * // examples/<app>/website/src/pages-impl/blog-post-en.bridge.tsx\n * import type { ComponentType } from 'react';\n *\n * import { createWebsiteBlogPostBridgeIsland }\n * from '@wildo-ai/saas-website/mdx';\n * import { BLOG_POST_MDX_COMPONENTS }\n * from './blog-post.mdx-components';\n * import { WEBSITE_ROOT_CONFIG } from '../website-root.config';\n *\n * // Static analyzable glob — Vite resolves at build time. The glob\n * // pattern MUST be a single string literal (no concatenation, no\n * // variable interpolation); Vite parses it AST-side. The `as` cast\n * // narrows the unknown record to the per-MDX-file shape Astro's mdx\n * // integration emits (default export = the compiled React component).\n * const rawModules = import.meta.glob('./content/blog/en/*.mdx', {\n * eager: true,\n * }) as Record<string, { default: ComponentType }>;\n *\n * const slugToMdxBody: Record<string, ComponentType> = {};\n * for (const [path, mod] of Object.entries(rawModules)) {\n * // './content/blog/en/why-context.mdx' -> 'why-context'\n * const slug = path.split('/').pop()!.replace(/\\.mdx$/, '');\n * slugToMdxBody[slug] = mod.default;\n * }\n *\n * export const BlogPostEnBridgeIsland =\n * createWebsiteBlogPostBridgeIsland({\n * slugToMdxBody,\n * navigation: WEBSITE_ROOT_CONFIG.navigation,\n * mdxComponents: BLOG_POST_MDX_COMPONENTS,\n * });\n * ```\n *\n * **Per-locale `[slug].astro` shell** (consumer side):\n *\n * ```astro\n * ---\n * import { getCollection } from 'astro:content';\n * import {\n * loadWebsitePageRuntime,\n * renderBlogPostHeadHtml,\n * renderWebsiteDesignTokensCss,\n * } from '@wildo-ai/saas-website/astro';\n * import { parseBlogPostFrontmatter } from '@wildo-ai/saas-website/mdx';\n * import { BlogPostEnBridgeIsland } from '@/pages-impl/blog-post-en.bridge';\n * import { BLOG_POST_PAGE_MANIFEST } from '@/pages-impl/blog-post.page';\n * import { WEBSITE_SITE_CONTEXT } from '@/website-site-context';\n *\n * export async function getStaticPaths() {\n * const posts = await getCollection('blog');\n * const defaultLocale = WEBSITE_SITE_CONTEXT.websiteConfig.defaultLocale;\n * return posts\n * .filter((p) => p.data.locale === defaultLocale)\n * .map((p) => ({ params: { slug: p.data.slug }, props: { entry: p } }));\n * }\n * const { entry } = Astro.props;\n *\n * const runtime = loadWebsitePageRuntime({\n * manifest: BLOG_POST_PAGE_MANIFEST,\n * siteContext: WEBSITE_SITE_CONTEXT,\n * labelPacksDir: './src/i18n',\n * astroLocale: Astro.currentLocale,\n * });\n * const frontmatter = parseBlogPostFrontmatter(entry.data, { source: entry.id });\n * const headHtml = renderBlogPostHeadHtml({\n * siteContext: WEBSITE_SITE_CONTEXT,\n * locale: runtime.locale,\n * routePath: `/blog/${frontmatter.slug}`,\n * frontmatter,\n * });\n * const designTokensCss = renderWebsiteDesignTokensCss(\n * WEBSITE_SITE_CONTEXT.rootConfig.designTokens,\n * );\n * ---\n * <!doctype html>\n * <html lang={runtime.locale}>\n * <head>\n * <meta charset=\"UTF-8\" />\n * <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n * <Fragment set:html={headHtml} />\n * <style set:html={designTokensCss}></style>\n * </head>\n * <body>\n * <BlogPostEnBridgeIsland\n * client:load\n * slug={frontmatter.slug}\n * rawFrontmatter={entry.data}\n * source={entry.id}\n * locale={runtime.locale}\n * defaultLocale={runtime.defaultLocale}\n * labelPack={runtime.labelPack}\n * designTokens={WEBSITE_SITE_CONTEXT.rootConfig.designTokens}\n * skipToMainContentLabelKey={\n * WEBSITE_SITE_CONTEXT.rootConfig.skipToMainContentLabelKey\n * }\n * />\n * </body>\n * </html>\n * ```\n *\n * # Boundary\n *\n * Strictly client-bundle-safe (re-exported from `mdx.ts` — NOT from\n * `astro-island.ts`, because this module hard-imports the MDX adapter\n * whose `@mdx-js/react` peer is optional; walked by the\n * bundle-isolation test). MUST stay clear of `node:*` and SSR-tier\n * specifiers.\n */\n\n/**\n * Module-load-time dependencies — closed over inside the returned\n * island. NEVER cross the hydration boundary as serialized props.\n */\nexport interface CreateWebsiteBlogPostBridgeIslandDeps {\n /**\n * Per-slug map of compiled MDX bodies (each entry is a React\n * component — the `.default` export of the MDX module). Typically\n * built from `import.meta.glob('./content/blog/<locale>/*.mdx',\n * { eager: true })` with the path-key normalized to the slug. Closed\n * over at module-load time so the entire MDX body graph for the\n * locale lands inside ONE React island bundle (D-6 Option A) — this\n * is the structural fix for Astro's React-children context-propagation\n * gap (see file preamble).\n *\n * The map is read by `slugToMdxBody[props.slug]` at island render\n * time. A missing slug throws a clear framework-owned error (rather than\n * rendering an empty body silently); the consumer's `getStaticPaths`\n * is responsible for not emitting routes for slugs absent from the\n * map.\n *\n * **Why `ComponentType<any>` and not a stricter generic**: matches\n * the upstream `@mdx-js/react` convention (`MDXContent` from\n * `mdx/types` is parameterized over an open `MDXProps` shape). MDX\n * compilation hands the body a compiler-managed props object that\n * the type system cannot narrow at the framework boundary; using\n * `<any>` here keeps the consumer's\n * `import.meta.glob(...) as Record<string, { default: ComponentType }>`\n * cast assignable without an additional wrap/unwrap. Same posture\n * as `WebsiteMdxComponentsMap` (intentional symmetry).\n */\n slugToMdxBody: Readonly<Record<string, ComponentType<any>>>;\n /**\n * Site-wide navigation slot bindings (header / footer components).\n * Closed over here for the same reason as the page bridge: both\n * fields are `ComponentType` refs that cannot survive Astro's\n * serialization boundary.\n */\n navigation: WebsiteNavigationConfig;\n /**\n * MDX-tag → React-component map forwarded into `<BlogPost>` and\n * scoped via `<WebsiteMdxProvider>`. Typically a small object\n * literal exporting the consumer-authored business sections that\n * blog posts can embed (`<CTASection />`, etc.). Closed over here\n * (rather than passed as an island prop) because the values are\n * `ComponentType` refs.\n */\n mdxComponents?: WebsiteMdxComponentsMap;\n}\n\n/**\n * Hydration-boundary props — what the consumer's `.astro` page passes\n * to `<BlogPostEnBridgeIsland client:load ...{primitiveProps}/>`.\n * Every field is JSON-serializable.\n */\nexport interface WebsiteBlogPostBridgeIslandProps {\n /**\n * Slug of the post being rendered. Used by the island to look up\n * the matching MDX body in `deps.slugToMdxBody`. Carried as a plain\n * string (not the branded `BlogPostSlug`) because Astro's\n * serialization boundary unwraps brands.\n */\n slug: string;\n /**\n * Raw frontmatter object Astro hands the page from `entry.data`.\n * Forwarded straight to `<BlogPost>` for strict Zod-4 validation.\n * The bridge does NOT re-validate (single validation surface, owned\n * by the renderer).\n */\n rawFrontmatter: unknown;\n /**\n * Diagnostic source identifier echoed into validation errors —\n * typically `entry.id` from Astro's content collection. Optional\n * but recommended for actionable error messages.\n */\n source?: string;\n /** The locale Astro resolved (with default-locale fallback). */\n locale: AvailableLanguage;\n /**\n * The site's default locale. Required for `WebsiteInternalLink`\n * locale-prefix logic (mirrors the page bridge's `defaultLocale`\n * island prop).\n */\n defaultLocale: AvailableLanguage;\n /** Already-loaded + already-shape-validated label pack. */\n labelPack: LabelPack;\n /** Design-token bundle from `WebsiteRootConfig.designTokens`. */\n designTokens: WebsiteDesignTokens;\n /**\n * Fully-composed label key the framework reads to render the\n * \"Skip to main content\" affordance. Mirrors\n * `WebsiteRootConfig.skipToMainContentLabelKey`. Carried as a\n * primitive island prop for the same reason as the page bridge.\n */\n skipToMainContentLabelKey: WebsiteLabelKey;\n /** Optional website-facing public providers materialized at build time. */\n frontendProviders?: FrontendProvidersBlock;\n /**\n * The CODE channel for those providers (#332): the\n * `generatedFrontendProviderModules` export of this website service's own\n * `src/generated/frontend-providers.generated.ts`, written by\n * `wildo config sync`.\n *\n * `frontendProviders` above says WHICH providers this service turned on, in\n * this environment; this says what code the bundle actually contains for\n * them. Both are needed, because a JSON payload cannot carry an SDK loader\n * and a bundle cannot know which environment it is running in.\n *\n * NOT a JSON-serializable island prop like its siblings, and it does not need\n * to be: the bridge module is bundled with the page, so the generated module\n * map is an ordinary import in the same graph rather than something that has\n * to cross the hydration boundary.\n *\n * Omitted is the ordinary case for a website declaring no package-shipped\n * provider: no such file is generated, so there is nothing to import.\n */\n frontendProviderModules?: GeneratedWebsiteProviderModules;\n}\n\nconst EMPTY_MDX_COMPONENTS: WebsiteMdxComponentsMap = Object.freeze({});\n\n/**\n * Returns a FUNCTION component, not the wider `ComponentType` union. The island IS a function\n * component — Astro hydrates nothing else here — and the union is not callable, so declaring it\n * cost callers the ability to invoke the island directly (which the bridge suites do, to observe\n * the synchronous throw for an unregistered slug without routing it through React's reconciler\n * error path). `FunctionComponent` is assignable to `ComponentType`, so no consumer narrows.\n */\nexport function createWebsiteBlogPostBridgeIsland(\n deps: CreateWebsiteBlogPostBridgeIslandDeps,\n): FunctionComponent<WebsiteBlogPostBridgeIslandProps> {\n const {\n slugToMdxBody,\n navigation,\n mdxComponents = EMPTY_MDX_COMPONENTS,\n } = deps;\n\n function WebsiteBlogPostBridgeIsland({\n slug,\n rawFrontmatter,\n source,\n locale,\n defaultLocale,\n labelPack,\n designTokens,\n skipToMainContentLabelKey,\n frontendProviders,\n frontendProviderModules,\n }: WebsiteBlogPostBridgeIslandProps): ReactNode {\n const MdxBody = slugToMdxBody[slug];\n if (MdxBody === undefined) {\n /**\n * Loud failure — the consumer's `getStaticPaths` is supposed to\n * only emit routes for slugs present in the MDX glob. A missing\n * lookup means the glob and the collection are out of sync; the\n * operator needs an actionable error string with the offending\n * slug + the keys that ARE present (truncated to keep the build\n * log readable).\n */\n const knownKeys = Object.keys(slugToMdxBody);\n const known =\n knownKeys.length <= 5\n ? knownKeys.join(', ')\n : `${knownKeys.slice(0, 5).join(', ')}, … (${knownKeys.length} total)`;\n throw new Error(\n `[blog-post-bridge] No MDX body registered for slug=\"${slug}\". ` +\n `The bridge factory's slugToMdxBody map only knows: ${known}. ` +\n `Verify the consumer's import.meta.glob('...content/blog/<locale>/*.mdx') ` +\n `pattern matches the source file naming.`,\n );\n }\n\n const runtimeValue: WebsiteRuntimeContextValue = {\n locale,\n defaultLocale,\n labelPack,\n designTokens,\n navigation,\n skipToMainContentLabelKey,\n frontendProviderRegistry: createFrontendWebsiteProviderRegistry({\n entries: frontendProviders,\n modules: frontendProviderModules,\n }),\n };\n return (\n <WebsiteRuntimeContextProvider value={runtimeValue}>\n <BlogPost\n rawFrontmatter={rawFrontmatter}\n source={source}\n mdxComponents={mdxComponents}\n >\n <MdxBody />\n </BlogPost>\n </WebsiteRuntimeContextProvider>\n );\n }\n WebsiteBlogPostBridgeIsland.displayName = 'WebsiteBlogPostBridgeIsland';\n\n return WebsiteBlogPostBridgeIsland;\n}\n\n/**\n * Re-export of the framework-reserved blog-post page ref. Consumers\n * authoring `BLOG_POST_PAGE_MANIFEST` need this constant to satisfy\n * the manifest's `ref` field; re-exporting it from the bridge module\n * means the consumer's per-locale bridge file can grab both symbols\n * from the one `@wildo-ai/saas-website/mdx` import it already has.\n */\nexport { BLOG_POST_PAGE_REF };\n/** @wildo_source:part:end saas.website.blog.bridge */\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"blog-post-head.renderer.d.ts","sourceRoot":"","sources":["../../../../src/astro/blog-post-head.renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAG9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sDAAsD,CAAC;AAChG,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mEAAmE,CAAC;AAItH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAEH,MAAM,WAAW,6BAA6B;IAC5C;;;;;;;;;OASG;IACH,WAAW,EAAE,kBAAkB,CAAC;IAChC;;;;OAIG;IACH,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,WAAW,EAAE,mBAAmB,CAAC;IACjC;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,yCAAyC;IACxD,WAAW,EAAE,mBAAmB,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,yCAAyC,GAC9C,4BAA4B,CAuB9B;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,6BAA6B,GAAG,MAAM,CAkIlF;AACD,6DAA6D"}
1
+ {"version":3,"file":"blog-post-head.renderer.d.ts","sourceRoot":"","sources":["../../../src/astro/blog-post-head.renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAG9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sDAAsD,CAAC;AAChG,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mEAAmE,CAAC;AAItH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAEH,MAAM,WAAW,6BAA6B;IAC5C;;;;;;;;;OASG;IACH,WAAW,EAAE,kBAAkB,CAAC;IAChC;;;;OAIG;IACH,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,WAAW,EAAE,mBAAmB,CAAC;IACjC;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,yCAAyC;IACxD,WAAW,EAAE,mBAAmB,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,yCAAyC,GAC9C,4BAA4B,CAuB9B;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,6BAA6B,GAAG,MAAM,CAkIlF;AACD,6DAA6D"}
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-runtime.d.ts","sourceRoot":"","sources":["../../../../src/astro/bridge-runtime.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAa,MAAM,OAAO,CAAC;AAEzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAO9E,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,+DAA+D,CAAC;AAErH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+DAA+D,CAAC;AACzG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC;AACvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyHG;AAEH;;;GAGG;AACH,MAAM,WAAW,iCAAiC;IAChD;;;;;;;;;;;;;;OAcG;IACH,aAAa,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC;;;;OAIG;IACH,OAAO,EAAE,cAAc,CAAC;IACxB;;;;;OAKG;IACH,UAAU,EAAE,uBAAuB,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC3C,gEAAgE;IAChE,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;;;;;;OASG;IACH,aAAa,EAAE,iBAAiB,CAAC;IACjC,2DAA2D;IAC3D,SAAS,EAAE,SAAS,CAAC;IACrB,iEAAiE;IACjE,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;;;;;;;OAUG;IACH,yBAAyB,EAAE,eAAe,CAAC;IAC3C,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAC3C;;;;;;;;;;;;;;;;;;OAkBG;IACH,uBAAuB,CAAC,EAAE,+BAA+B,CAAC;IAC1D;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,iCAAiC,GACtC,iBAAiB,CAAC,4BAA4B,CAAC,CAuCjD;AACD,uDAAuD"}
1
+ {"version":3,"file":"bridge-runtime.d.ts","sourceRoot":"","sources":["../../../src/astro/bridge-runtime.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAa,MAAM,OAAO,CAAC;AAEzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAO9E,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,+DAA+D,CAAC;AAErH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+DAA+D,CAAC;AACzG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC;AACvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyHG;AAEH;;;GAGG;AACH,MAAM,WAAW,iCAAiC;IAChD;;;;;;;;;;;;;;OAcG;IACH,aAAa,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC;;;;OAIG;IACH,OAAO,EAAE,cAAc,CAAC;IACxB;;;;;OAKG;IACH,UAAU,EAAE,uBAAuB,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC3C,gEAAgE;IAChE,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;;;;;;OASG;IACH,aAAa,EAAE,iBAAiB,CAAC;IACjC,2DAA2D;IAC3D,SAAS,EAAE,SAAS,CAAC;IACrB,iEAAiE;IACjE,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;;;;;;;OAUG;IACH,yBAAyB,EAAE,eAAe,CAAC;IAC3C,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAC3C;;;;;;;;;;;;;;;;;;OAkBG;IACH,uBAAuB,CAAC,EAAE,+BAA+B,CAAC;IAC1D;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,iCAAiC,GACtC,iBAAiB,CAAC,4BAA4B,CAAC,CAuCjD;AACD,uDAAuD"}
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-runtime.js","sourceRoot":"","sources":["../../../../src/astro/bridge-runtime.tsx"],"names":[],"mappings":";AAKA,OAAO,EACL,6BAA6B,GAE9B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,qCAAqC,EAAE,MAAM,+DAA+D,CAAC;AAEtH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AA4PtE;;;;;;GAMG;AACH,MAAM,UAAU,6BAA6B,CAC3C,IAAuC;IAEvC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAEpD,SAAS,uBAAuB,CAAC,EAC/B,MAAM,EACN,aAAa,EACb,SAAS,EACT,YAAY,EACZ,yBAAyB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,SAAS,EACT,SAAS,GACoB;QAC7B,MAAM,YAAY,GAA+B;YAC/C,MAAM;YACN,aAAa;YACb,SAAS;YACT,YAAY;YACZ,UAAU;YACV,yBAAyB;YACzB,wBAAwB,EAAE,qCAAqC,CAAC;gBAC9D,OAAO,EAAE,iBAAiB;gBAC1B,OAAO,EAAE,uBAAuB;aACjC,CAAC;YACF,SAAS;YACT,SAAS;SACV,CAAC;QACF,OAAO,CACL,KAAC,6BAA6B,IAAC,KAAK,EAAE,YAAY,YAChD,KAAC,iBAAiB,IAAC,OAAO,EAAE,OAAO,YACjC,KAAC,aAAa,KAAG,GACC,GACU,CACjC,CAAC;IACJ,CAAC;IACD,uBAAuB,CAAC,WAAW,GAAG,yBAAyB,CAAC;IAEhE,OAAO,uBAAuB,CAAC;AACjC,CAAC","sourcesContent":["import type { ComponentType, FunctionComponent, ReactNode } from 'react';\n\nimport type { FrontendProvidersBlock } from '@wildo-ai/saas-models/public-runtime';\nimport type { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';\n\nimport {\n WebsiteRuntimeContextProvider,\n type WebsiteRuntimeContextValue,\n} from '../core/contexts/WebsiteRuntimeContext';\nimport { createFrontendWebsiteProviderRegistry } from '../core/external-providers/frontend-provider-registry.website';\nimport type { GeneratedWebsiteProviderModules } from '../core/external-providers/frontend-provider-registry.website';\nimport { WebsitePageLayout } from '../core/layouts/WebsitePageLayout';\nimport type { WebsiteDesignTokens } from '../schemas/design-tokens/website-design-tokens.shared.schemas';\nimport type { WebsiteLabelKey } from '../schemas/label-keys/website-label-key.schemas';\nimport type { WebsiteNavigationConfig } from '../schemas/manifests/website-root-config.shared.schemas';\nimport type { WebsitePageRef } from '../schemas/refs/page-ref.schemas';\nimport type { LabelPack } from '../schemas/validators/label-pack.validator';\n\n/**\n * @wildo_source:part:start saas.website.astro.bridge facet:layer:astro facet:family:website\n *\n * `createWebsitePageBridgeIsland(deps)` — factory that returns the\n * React island a consumer's per-page `.astro` file mounts with a\n * `client:idle` (or `client:load`) directive.\n *\n * **The hard architectural constraint this design solves**: Astro\n * serializes React-island props via `devalue`-style JSON to transfer\n * them across the SSR → client-hydration boundary. Function values —\n * including `ComponentType` references — are NOT serializable. Any\n * design that tried to pass `pageComponent`, `headerComponent`, or\n * `footerComponent` AS island props would render correctly server-side\n * (the function ref is in-process during SSR) and then mismatch on\n * first hydration (the client receives `undefined`/broken placeholders\n * for the function-typed fields). The Vitest suite would not catch\n * this because Vitest renders React in a single process — there is no\n * serialization boundary in unit tests.\n *\n * **The factory pattern fixes the constraint by closing over** the\n * `pageComponent`, `pageRef`, and `navigation` (header / footer\n * component refs) at MODULE LOAD TIME on the consumer side. The\n * returned island accepts only PRIMITIVE-VALUED props (`locale`,\n * `labelPack`, `designTokens`) — all JSON-serializable, all safe to\n * cross the hydration boundary. The component refs never appear in\n * the prop signature; they live in the lexical closure that the\n * client-side bundle includes naturally as part of the island's\n * compiled module.\n *\n * **Authoring pattern (per-page bridge module)**:\n *\n * ```tsx\n * // consumer's src/pages-impl/landing.bridge.tsx\n * import { createWebsitePageBridgeIsland } from '@wildo-ai/saas-website/astro-island';\n * import { LandingPage, LANDING_PAGE_MANIFEST } from './landing.page';\n * import { WEBSITE_ROOT_CONFIG } from '../website-root.config';\n *\n * export const LandingBridgeIsland = createWebsitePageBridgeIsland({\n * PageComponent: LandingPage,\n * pageRef: LANDING_PAGE_MANIFEST.ref,\n * navigation: WEBSITE_ROOT_CONFIG.navigation,\n * });\n * ```\n *\n * ```astro\n * ---\n * // consumer's src/pages/index.astro\n * import {\n * loadWebsitePageRuntime,\n * renderWebsitePageHeadHtml,\n * renderWebsiteDesignTokensCss,\n * } from '@wildo-ai/saas-website/astro';\n * import { LandingBridgeIsland } from '../pages-impl/landing.bridge';\n * import { LANDING_PAGE_MANIFEST } from '../pages-impl/landing.page';\n * import { WEBSITE_ROOT_CONFIG } from '../website-root.config';\n *\n * const runtime = loadWebsitePageRuntime({\n * manifest: LANDING_PAGE_MANIFEST,\n * rootConfig: WEBSITE_ROOT_CONFIG,\n * labelPacksDir: './src/i18n',\n * astroLocale: Astro.currentLocale,\n * });\n * const headHtml = renderWebsitePageHeadHtml({\n * manifest: LANDING_PAGE_MANIFEST,\n * rootConfig: WEBSITE_ROOT_CONFIG,\n * locale: runtime.locale,\n * labelPack: runtime.labelPack,\n * });\n * const designTokensCss = renderWebsiteDesignTokensCss(\n * WEBSITE_ROOT_CONFIG.designTokens,\n * );\n * ---\n * <!doctype html>\n * <html lang={runtime.locale}>\n * <head>\n * <Fragment set:html={headHtml} />\n * <style set:html={designTokensCss}></style>\n * </head>\n * <body>\n * <LandingBridgeIsland\n * client:idle\n * locale={runtime.locale}\n * labelPack={runtime.labelPack}\n * designTokens={WEBSITE_ROOT_CONFIG.designTokens}\n * />\n * </body>\n * </html>\n * ```\n *\n * **Why a per-page bridge file** (rather than constructing the island\n * inline in the consumer's `.astro` frontmatter):\n *\n * Astro's `client:*` directive requires the JSX tag to reference a\n * statically-resolvable module export at compile time — that is how\n * Astro knows which module to bundle for client-side hydration. A\n * factory call inside `.astro` frontmatter (`const Island =\n * createWebsitePageBridgeIsland({...}); <Island client:idle/>`) does\n * NOT round-trip through Astro's module-graph analyzer: Astro would\n * see a runtime-constructed component reference and fail to bundle\n * the closure for the client. The per-page bridge file gives Astro a\n * static export to bind the directive to. The cost is one ~6-line\n * file per page; the win is the only architecture that is safe\n * against the H-2 hydration-mismatch failure mode AND uses Astro's\n * native bundling pipeline.\n *\n * **Why `ComponentType` refs in `Deps` and not in `Props`**: this is\n * the entire point of the redesign. `Deps` is consumed at module load\n * time on the consumer side — the closure traps the function refs\n * inside the returned component. `Props` is consumed at island-mount\n * time and crosses Astro's serialization boundary. Keeping the two\n * concerns lexically separate makes the boundary visible in the type\n * signature.\n *\n * **Boundary** (D12 client-bundle discipline): this module ships into\n * the React-island bundle. It MUST stay clear of `node:*` imports,\n * fs / path helpers, and the SSR-tier specifiers\n * (`axios`, `jsonwebtoken`, …). The bundle-isolation test catches\n * regressions both globally (closure-wide allow-list) AND with the\n * targeted Phase-5 negative test that asserts `node:fs` / `node:path`\n * reach this island closure ONLY through `astro.ts`, never through\n * `index.ts` or `companion-exports.ts`.\n */\n\n/**\n * Module-load-time dependencies — closed over inside the returned\n * island. NEVER cross the hydration boundary as serialized props.\n */\nexport interface CreateWebsitePageBridgeIslandDeps {\n /**\n * The page's React component. Typically the same value that was\n * passed to `defineWebsitePageManifest({ pageComponent })` — the\n * authoring convention re-imports it here to keep the closure\n * explicit and the per-page bridge file self-contained.\n *\n * Typed as `ComponentType<any>` to mirror\n * `WebsitePageManifest.pageComponent` and dodge React's `ComponentType`\n * contravariance: a narrower `ComponentType<TProps>` returned by\n * `defineWebsitePageManifest<TProps>` would not be assignable to a\n * `ComponentType<unknown>` slot, blocking every per-page bridge\n * call site. The component is invoked with no props at the\n * `<PageComponent />` JSX call site below, so widening here is\n * runtime-safe.\n */\n PageComponent: ComponentType<any>;\n /**\n * The active page's ref. Carried as a primitive (string-branded)\n * value so the inner `WebsitePageLayout` can register the\n * `WebsitePageContext` without re-resolving it from the manifest.\n */\n pageRef: WebsitePageRef;\n /**\n * Site-wide navigation slot bindings (header / footer components).\n * Closed over here rather than passed as island props because both\n * fields are `ComponentType` refs that cannot survive Astro's\n * serialization boundary.\n */\n navigation: WebsiteNavigationConfig;\n}\n\n/**\n * Hydration-boundary props — what the consumer's `.astro` page passes\n * to `<LandingBridgeIsland client:idle ...{primitiveProps}/>`. Every\n * field is JSON-serializable.\n */\nexport interface WebsitePageBridgeIslandProps {\n /** The locale Astro resolved (with default-locale fallback). */\n locale: AvailableLanguage;\n /**\n * The site's default locale. Carried as an island prop (not closed\n * over in `Deps`) because it is JSON-primitive and consumers\n * already pass `runtime.locale` from the per-locale Astro page\n * frontmatter — passing the matching `runtime.defaultLocale` from\n * the same `loadWebsitePageRuntime(...)` return value keeps the\n * authoring story symmetric. Required for `WebsiteInternalLink`\n * (Phase 6 fix H-β) which needs both locales to compute the\n * correct prefix.\n */\n defaultLocale: AvailableLanguage;\n /** Already-loaded + already-shape-validated label pack. */\n labelPack: LabelPack;\n /** Design-token bundle from `WebsiteRootConfig.designTokens`. */\n designTokens: WebsiteDesignTokens;\n /**\n * Fully-composed label key the framework reads to render the\n * \"Skip to main content\" affordance (Phase 6 third audit fix M-α).\n * Mirrors `WebsiteRootConfig.skipToMainContentLabelKey`. Carried as\n * a JSON-serializable string prop (NOT closed over in `Deps`)\n * because it is a primitive value the consumer already has on the\n * root config in the `.astro` frontmatter — passing it as an island\n * prop keeps the per-page bridge module dependency-free of the\n * site root config (the bridge stays page-local; only the per-page\n * `.astro` page knows about `WEBSITE_ROOT_CONFIG`).\n */\n skipToMainContentLabelKey: WebsiteLabelKey;\n /** Optional website-facing public providers materialized at build time. */\n frontendProviders?: FrontendProvidersBlock;\n /**\n * The CODE channel for those providers (#332): the\n * `generatedFrontendProviderModules` export of this website service's own\n * `src/generated/frontend-providers.generated.ts`, written by\n * `wildo config sync`.\n *\n * `frontendProviders` above says WHICH providers this service turned on, in\n * this environment; this says what code the bundle actually contains for\n * them. Both are needed, because a JSON payload cannot carry an SDK loader\n * and a bundle cannot know which environment it is running in.\n *\n * NOT a JSON-serializable island prop like its siblings, and it does not need\n * to be: the bridge module is bundled with the page, so the generated module\n * map is an ordinary import in the same graph rather than something that has\n * to cross the hydration boundary.\n *\n * Omitted is the ordinary case for a website declaring no package-shipped\n * provider: no such file is generated, so there is nothing to import.\n */\n frontendProviderModules?: GeneratedWebsiteProviderModules;\n /**\n * Optional backend API origin (no trailing slash) forwarded into\n * `WebsiteRuntimeContext.apiOrigin` for anonymous-capture sections\n * (lead / draft-note forms) to construct their\n * `WebsiteAnonymousSessionClient`. A JSON-serializable string, so it\n * crosses the hydration boundary as an island prop; the `.astro` page\n * resolves the per-environment value from\n * `WildoMarketingWebsiteConfig.apiOrigin`. Omitted on pages with no\n * capture section.\n */\n apiOrigin?: string;\n /**\n * The product origin this site's self-serve CTAs link to (\"Start free\",\n * \"Get started\"), forwarded into `WebsiteRuntimeContext.appOrigin` (#493).\n *\n * An island prop for the same reason `apiOrigin` above is one: the `.astro`\n * page resolves it from `WildoMarketingWebsiteConfig.appOrigin`, which is\n * Node-loaded and invisible to a client island. Before this, a site\n * resolved the product origin a SECOND time from a public build-time\n * environment variable — one host authored twice with no mechanical link,\n * and a silent fallback to localhost when the variable was unset.\n *\n * Optional because a page with no CTA needs none; a page that renders one\n * without passing this should fail LOUDLY rather than fall back, which is\n * the consumer's job and the whole point of removing the fallback.\n */\n appOrigin?: string;\n}\n\n/**\n * Returns a FUNCTION component, not the wider `ComponentType` union. The island IS a function\n * component — Astro hydrates nothing else here — and the union is not callable, so the wider\n * declaration cost callers the ability to invoke the island directly. Mirrors\n * `createWebsiteBlogPostBridgeIsland`, whose suite depends on that call. `FunctionComponent` is\n * assignable to `ComponentType`, so no consumer narrows.\n */\nexport function createWebsitePageBridgeIsland(\n deps: CreateWebsitePageBridgeIslandDeps,\n): FunctionComponent<WebsitePageBridgeIslandProps> {\n const { PageComponent, pageRef, navigation } = deps;\n\n function WebsitePageBridgeIsland({\n locale,\n defaultLocale,\n labelPack,\n designTokens,\n skipToMainContentLabelKey,\n frontendProviders,\n frontendProviderModules,\n apiOrigin,\n appOrigin,\n }: WebsitePageBridgeIslandProps): ReactNode {\n const runtimeValue: WebsiteRuntimeContextValue = {\n locale,\n defaultLocale,\n labelPack,\n designTokens,\n navigation,\n skipToMainContentLabelKey,\n frontendProviderRegistry: createFrontendWebsiteProviderRegistry({\n entries: frontendProviders,\n modules: frontendProviderModules,\n }),\n apiOrigin,\n appOrigin,\n };\n return (\n <WebsiteRuntimeContextProvider value={runtimeValue}>\n <WebsitePageLayout pageRef={pageRef}>\n <PageComponent />\n </WebsitePageLayout>\n </WebsiteRuntimeContextProvider>\n );\n }\n WebsitePageBridgeIsland.displayName = 'WebsitePageBridgeIsland';\n\n return WebsitePageBridgeIsland;\n}\n/** @wildo_source:part:end saas.website.astro.bridge */\n"]}
1
+ {"version":3,"file":"bridge-runtime.js","sourceRoot":"","sources":["../../../src/astro/bridge-runtime.tsx"],"names":[],"mappings":";AAKA,OAAO,EACL,6BAA6B,GAE9B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,qCAAqC,EAAE,MAAM,+DAA+D,CAAC;AAEtH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AA4PtE;;;;;;GAMG;AACH,MAAM,UAAU,6BAA6B,CAC3C,IAAuC;IAEvC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAEpD,SAAS,uBAAuB,CAAC,EAC/B,MAAM,EACN,aAAa,EACb,SAAS,EACT,YAAY,EACZ,yBAAyB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,SAAS,EACT,SAAS,GACoB;QAC7B,MAAM,YAAY,GAA+B;YAC/C,MAAM;YACN,aAAa;YACb,SAAS;YACT,YAAY;YACZ,UAAU;YACV,yBAAyB;YACzB,wBAAwB,EAAE,qCAAqC,CAAC;gBAC9D,OAAO,EAAE,iBAAiB;gBAC1B,OAAO,EAAE,uBAAuB;aACjC,CAAC;YACF,SAAS;YACT,SAAS;SACV,CAAC;QACF,OAAO,CACL,KAAC,6BAA6B,IAAC,KAAK,EAAE,YAAY,YAChD,KAAC,iBAAiB,IAAC,OAAO,EAAE,OAAO,YACjC,KAAC,aAAa,KAAG,GACC,GACU,CACjC,CAAC;IACJ,CAAC;IACD,uBAAuB,CAAC,WAAW,GAAG,yBAAyB,CAAC;IAEhE,OAAO,uBAAuB,CAAC;AACjC,CAAC","sourcesContent":["import type { ComponentType, FunctionComponent, ReactNode } from 'react';\n\nimport type { FrontendProvidersBlock } from '@wildo-ai/saas-models/public-runtime';\nimport type { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';\n\nimport {\n WebsiteRuntimeContextProvider,\n type WebsiteRuntimeContextValue,\n} from '../core/contexts/WebsiteRuntimeContext';\nimport { createFrontendWebsiteProviderRegistry } from '../core/external-providers/frontend-provider-registry.website';\nimport type { GeneratedWebsiteProviderModules } from '../core/external-providers/frontend-provider-registry.website';\nimport { WebsitePageLayout } from '../core/layouts/WebsitePageLayout';\nimport type { WebsiteDesignTokens } from '../schemas/design-tokens/website-design-tokens.shared.schemas';\nimport type { WebsiteLabelKey } from '../schemas/label-keys/website-label-key.schemas';\nimport type { WebsiteNavigationConfig } from '../schemas/manifests/website-root-config.shared.schemas';\nimport type { WebsitePageRef } from '../schemas/refs/page-ref.schemas';\nimport type { LabelPack } from '../schemas/validators/label-pack.validator';\n\n/**\n * @wildo_source:part:start saas.website.astro.bridge facet:layer:astro facet:family:website\n *\n * `createWebsitePageBridgeIsland(deps)` — factory that returns the\n * React island a consumer's per-page `.astro` file mounts with a\n * `client:idle` (or `client:load`) directive.\n *\n * **The hard architectural constraint this design solves**: Astro\n * serializes React-island props via `devalue`-style JSON to transfer\n * them across the SSR → client-hydration boundary. Function values —\n * including `ComponentType` references — are NOT serializable. Any\n * design that tried to pass `pageComponent`, `headerComponent`, or\n * `footerComponent` AS island props would render correctly server-side\n * (the function ref is in-process during SSR) and then mismatch on\n * first hydration (the client receives `undefined`/broken placeholders\n * for the function-typed fields). The Vitest suite would not catch\n * this because Vitest renders React in a single process — there is no\n * serialization boundary in unit tests.\n *\n * **The factory pattern fixes the constraint by closing over** the\n * `pageComponent`, `pageRef`, and `navigation` (header / footer\n * component refs) at MODULE LOAD TIME on the consumer side. The\n * returned island accepts only PRIMITIVE-VALUED props (`locale`,\n * `labelPack`, `designTokens`) — all JSON-serializable, all safe to\n * cross the hydration boundary. The component refs never appear in\n * the prop signature; they live in the lexical closure that the\n * client-side bundle includes naturally as part of the island's\n * compiled module.\n *\n * **Authoring pattern (per-page bridge module)**:\n *\n * ```tsx\n * // consumer's src/pages-impl/landing.bridge.tsx\n * import { createWebsitePageBridgeIsland } from '@wildo-ai/saas-website/astro-island';\n * import { LandingPage, LANDING_PAGE_MANIFEST } from './landing.page';\n * import { WEBSITE_ROOT_CONFIG } from '../website-root.config';\n *\n * export const LandingBridgeIsland = createWebsitePageBridgeIsland({\n * PageComponent: LandingPage,\n * pageRef: LANDING_PAGE_MANIFEST.ref,\n * navigation: WEBSITE_ROOT_CONFIG.navigation,\n * });\n * ```\n *\n * ```astro\n * ---\n * // consumer's src/pages/index.astro\n * import {\n * loadWebsitePageRuntime,\n * renderWebsitePageHeadHtml,\n * renderWebsiteDesignTokensCss,\n * } from '@wildo-ai/saas-website/astro';\n * import { LandingBridgeIsland } from '../pages-impl/landing.bridge';\n * import { LANDING_PAGE_MANIFEST } from '../pages-impl/landing.page';\n * import { WEBSITE_ROOT_CONFIG } from '../website-root.config';\n *\n * const runtime = loadWebsitePageRuntime({\n * manifest: LANDING_PAGE_MANIFEST,\n * rootConfig: WEBSITE_ROOT_CONFIG,\n * labelPacksDir: './src/i18n',\n * astroLocale: Astro.currentLocale,\n * });\n * const headHtml = renderWebsitePageHeadHtml({\n * manifest: LANDING_PAGE_MANIFEST,\n * rootConfig: WEBSITE_ROOT_CONFIG,\n * locale: runtime.locale,\n * labelPack: runtime.labelPack,\n * });\n * const designTokensCss = renderWebsiteDesignTokensCss(\n * WEBSITE_ROOT_CONFIG.designTokens,\n * );\n * ---\n * <!doctype html>\n * <html lang={runtime.locale}>\n * <head>\n * <Fragment set:html={headHtml} />\n * <style set:html={designTokensCss}></style>\n * </head>\n * <body>\n * <LandingBridgeIsland\n * client:idle\n * locale={runtime.locale}\n * labelPack={runtime.labelPack}\n * designTokens={WEBSITE_ROOT_CONFIG.designTokens}\n * />\n * </body>\n * </html>\n * ```\n *\n * **Why a per-page bridge file** (rather than constructing the island\n * inline in the consumer's `.astro` frontmatter):\n *\n * Astro's `client:*` directive requires the JSX tag to reference a\n * statically-resolvable module export at compile time — that is how\n * Astro knows which module to bundle for client-side hydration. A\n * factory call inside `.astro` frontmatter (`const Island =\n * createWebsitePageBridgeIsland({...}); <Island client:idle/>`) does\n * NOT round-trip through Astro's module-graph analyzer: Astro would\n * see a runtime-constructed component reference and fail to bundle\n * the closure for the client. The per-page bridge file gives Astro a\n * static export to bind the directive to. The cost is one ~6-line\n * file per page; the win is the only architecture that is safe\n * against the H-2 hydration-mismatch failure mode AND uses Astro's\n * native bundling pipeline.\n *\n * **Why `ComponentType` refs in `Deps` and not in `Props`**: this is\n * the entire point of the redesign. `Deps` is consumed at module load\n * time on the consumer side — the closure traps the function refs\n * inside the returned component. `Props` is consumed at island-mount\n * time and crosses Astro's serialization boundary. Keeping the two\n * concerns lexically separate makes the boundary visible in the type\n * signature.\n *\n * **Boundary** (D12 client-bundle discipline): this module ships into\n * the React-island bundle. It MUST stay clear of `node:*` imports,\n * fs / path helpers, and the SSR-tier specifiers\n * (`axios`, `jsonwebtoken`, …). The bundle-isolation test catches\n * regressions both globally (closure-wide allow-list) AND with the\n * targeted Phase-5 negative test that asserts `node:fs` / `node:path`\n * reach this island closure ONLY through `astro.ts`, never through\n * `index.ts` or `companion-exports.ts`.\n */\n\n/**\n * Module-load-time dependencies — closed over inside the returned\n * island. NEVER cross the hydration boundary as serialized props.\n */\nexport interface CreateWebsitePageBridgeIslandDeps {\n /**\n * The page's React component. Typically the same value that was\n * passed to `defineWebsitePageManifest({ pageComponent })` — the\n * authoring convention re-imports it here to keep the closure\n * explicit and the per-page bridge file self-contained.\n *\n * Typed as `ComponentType<any>` to mirror\n * `WebsitePageManifest.pageComponent` and dodge React's `ComponentType`\n * contravariance: a narrower `ComponentType<TProps>` returned by\n * `defineWebsitePageManifest<TProps>` would not be assignable to a\n * `ComponentType<unknown>` slot, blocking every per-page bridge\n * call site. The component is invoked with no props at the\n * `<PageComponent />` JSX call site below, so widening here is\n * runtime-safe.\n */\n PageComponent: ComponentType<any>;\n /**\n * The active page's ref. Carried as a primitive (string-branded)\n * value so the inner `WebsitePageLayout` can register the\n * `WebsitePageContext` without re-resolving it from the manifest.\n */\n pageRef: WebsitePageRef;\n /**\n * Site-wide navigation slot bindings (header / footer components).\n * Closed over here rather than passed as island props because both\n * fields are `ComponentType` refs that cannot survive Astro's\n * serialization boundary.\n */\n navigation: WebsiteNavigationConfig;\n}\n\n/**\n * Hydration-boundary props — what the consumer's `.astro` page passes\n * to `<LandingBridgeIsland client:idle ...{primitiveProps}/>`. Every\n * field is JSON-serializable.\n */\nexport interface WebsitePageBridgeIslandProps {\n /** The locale Astro resolved (with default-locale fallback). */\n locale: AvailableLanguage;\n /**\n * The site's default locale. Carried as an island prop (not closed\n * over in `Deps`) because it is JSON-primitive and consumers\n * already pass `runtime.locale` from the per-locale Astro page\n * frontmatter — passing the matching `runtime.defaultLocale` from\n * the same `loadWebsitePageRuntime(...)` return value keeps the\n * authoring story symmetric. Required for `WebsiteInternalLink`\n * (Phase 6 fix H-β) which needs both locales to compute the\n * correct prefix.\n */\n defaultLocale: AvailableLanguage;\n /** Already-loaded + already-shape-validated label pack. */\n labelPack: LabelPack;\n /** Design-token bundle from `WebsiteRootConfig.designTokens`. */\n designTokens: WebsiteDesignTokens;\n /**\n * Fully-composed label key the framework reads to render the\n * \"Skip to main content\" affordance (Phase 6 third audit fix M-α).\n * Mirrors `WebsiteRootConfig.skipToMainContentLabelKey`. Carried as\n * a JSON-serializable string prop (NOT closed over in `Deps`)\n * because it is a primitive value the consumer already has on the\n * root config in the `.astro` frontmatter — passing it as an island\n * prop keeps the per-page bridge module dependency-free of the\n * site root config (the bridge stays page-local; only the per-page\n * `.astro` page knows about `WEBSITE_ROOT_CONFIG`).\n */\n skipToMainContentLabelKey: WebsiteLabelKey;\n /** Optional website-facing public providers materialized at build time. */\n frontendProviders?: FrontendProvidersBlock;\n /**\n * The CODE channel for those providers (#332): the\n * `generatedFrontendProviderModules` export of this website service's own\n * `src/generated/frontend-providers.generated.ts`, written by\n * `wildo config sync`.\n *\n * `frontendProviders` above says WHICH providers this service turned on, in\n * this environment; this says what code the bundle actually contains for\n * them. Both are needed, because a JSON payload cannot carry an SDK loader\n * and a bundle cannot know which environment it is running in.\n *\n * NOT a JSON-serializable island prop like its siblings, and it does not need\n * to be: the bridge module is bundled with the page, so the generated module\n * map is an ordinary import in the same graph rather than something that has\n * to cross the hydration boundary.\n *\n * Omitted is the ordinary case for a website declaring no package-shipped\n * provider: no such file is generated, so there is nothing to import.\n */\n frontendProviderModules?: GeneratedWebsiteProviderModules;\n /**\n * Optional backend API origin (no trailing slash) forwarded into\n * `WebsiteRuntimeContext.apiOrigin` for anonymous-capture sections\n * (lead / draft-note forms) to construct their\n * `WebsiteAnonymousSessionClient`. A JSON-serializable string, so it\n * crosses the hydration boundary as an island prop; the `.astro` page\n * resolves the per-environment value from\n * `WildoMarketingWebsiteConfig.apiOrigin`. Omitted on pages with no\n * capture section.\n */\n apiOrigin?: string;\n /**\n * The product origin this site's self-serve CTAs link to (\"Start free\",\n * \"Get started\"), forwarded into `WebsiteRuntimeContext.appOrigin` (#493).\n *\n * An island prop for the same reason `apiOrigin` above is one: the `.astro`\n * page resolves it from `WildoMarketingWebsiteConfig.appOrigin`, which is\n * Node-loaded and invisible to a client island. Before this, a site\n * resolved the product origin a SECOND time from a public build-time\n * environment variable — one host authored twice with no mechanical link,\n * and a silent fallback to localhost when the variable was unset.\n *\n * Optional because a page with no CTA needs none; a page that renders one\n * without passing this should fail LOUDLY rather than fall back, which is\n * the consumer's job and the whole point of removing the fallback.\n */\n appOrigin?: string;\n}\n\n/**\n * Returns a FUNCTION component, not the wider `ComponentType` union. The island IS a function\n * component — Astro hydrates nothing else here — and the union is not callable, so the wider\n * declaration cost callers the ability to invoke the island directly. Mirrors\n * `createWebsiteBlogPostBridgeIsland`, whose suite depends on that call. `FunctionComponent` is\n * assignable to `ComponentType`, so no consumer narrows.\n */\nexport function createWebsitePageBridgeIsland(\n deps: CreateWebsitePageBridgeIslandDeps,\n): FunctionComponent<WebsitePageBridgeIslandProps> {\n const { PageComponent, pageRef, navigation } = deps;\n\n function WebsitePageBridgeIsland({\n locale,\n defaultLocale,\n labelPack,\n designTokens,\n skipToMainContentLabelKey,\n frontendProviders,\n frontendProviderModules,\n apiOrigin,\n appOrigin,\n }: WebsitePageBridgeIslandProps): ReactNode {\n const runtimeValue: WebsiteRuntimeContextValue = {\n locale,\n defaultLocale,\n labelPack,\n designTokens,\n navigation,\n skipToMainContentLabelKey,\n frontendProviderRegistry: createFrontendWebsiteProviderRegistry({\n entries: frontendProviders,\n modules: frontendProviderModules,\n }),\n apiOrigin,\n appOrigin,\n };\n return (\n <WebsiteRuntimeContextProvider value={runtimeValue}>\n <WebsitePageLayout pageRef={pageRef}>\n <PageComponent />\n </WebsitePageLayout>\n </WebsiteRuntimeContextProvider>\n );\n }\n WebsitePageBridgeIsland.displayName = 'WebsitePageBridgeIsland';\n\n return WebsitePageBridgeIsland;\n}\n/** @wildo_source:part:end saas.website.astro.bridge */\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"collect-expected-label-keys.d.ts","sourceRoot":"","sources":["../../../../src/astro/collect-expected-label-keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+DAA+D,CAAC;AAG9G,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,4CAA4C,CAAC;AAEhG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,SAAS,wBAAwB,EAAE,GAC5C,6BAA6B,CAsB/B;AAuBD,oEAAoE"}
1
+ {"version":3,"file":"collect-expected-label-keys.d.ts","sourceRoot":"","sources":["../../../src/astro/collect-expected-label-keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+DAA+D,CAAC;AAG9G,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,4CAA4C,CAAC;AAEhG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,SAAS,wBAAwB,EAAE,GAC5C,6BAA6B,CAsB/B;AAuBD,oEAAoE"}
@@ -1 +1 @@
1
- {"version":3,"file":"headers-renderer.d.ts","sourceRoot":"","sources":["../../../../src/astro/headers-renderer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAIjE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,kBAAkB,GAAG,MAAM,CAapF;AACD,iEAAiE;AAEjE;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,MAAM,CAgBT"}
1
+ {"version":3,"file":"headers-renderer.d.ts","sourceRoot":"","sources":["../../../src/astro/headers-renderer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAIjE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,kBAAkB,GAAG,MAAM,CAapF;AACD,iEAAiE;AAEjE;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,MAAM,CAgBT"}
@@ -1 +1 @@
1
- {"version":3,"file":"i18n-routing.helper.d.ts","sourceRoot":"","sources":["../../../../src/astro/i18n-routing.helper.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE;QACP;;;;;;;WAOG;QACH,mBAAmB,EAAE,OAAO,CAAC;QAC7B;;;;WAIG;QACH,uBAAuB,EAAE,OAAO,CAAC;KAClC,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,kBAAkB,GAAG,eAAe,CAsBrF;AACD,4DAA4D"}
1
+ {"version":3,"file":"i18n-routing.helper.d.ts","sourceRoot":"","sources":["../../../src/astro/i18n-routing.helper.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE;QACP;;;;;;;WAOG;QACH,mBAAmB,EAAE,OAAO,CAAC;QAC7B;;;;WAIG;QACH,uBAAuB,EAAE,OAAO,CAAC;KAClC,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,kBAAkB,GAAG,eAAe,CAsBrF;AACD,4DAA4D"}
@@ -1 +1 @@
1
- {"version":3,"file":"label-pack-loader.d.ts","sourceRoot":"","sources":["../../../../src/astro/label-pack-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAK9E,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,SAAS,EACd,KAAK,yBAAyB,EAC/B,MAAM,4CAA4C,CAAC;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,SAAS,CA4BpF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,kBAAkB,GAC9B,GAAG,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAMnC;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,yBAAyB,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,kBAAkB,EAC/B,wBAAwB,EAAE,6BAA6B,GACtD,SAAS,yBAAyB,EAAE,CAmBtC;AAgCD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,kBAAkB,EAC/B,wBAAwB,EAAE,6BAA6B,GACtD,IAAI,CA6DN;AA+ED,6DAA6D"}
1
+ {"version":3,"file":"label-pack-loader.d.ts","sourceRoot":"","sources":["../../../src/astro/label-pack-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAK9E,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,SAAS,EACd,KAAK,yBAAyB,EAC/B,MAAM,4CAA4C,CAAC;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,SAAS,CA4BpF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,kBAAkB,GAC9B,GAAG,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAMnC;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,yBAAyB,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,kBAAkB,EAC/B,wBAAwB,EAAE,6BAA6B,GACtD,SAAS,yBAAyB,EAAE,CAmBtC;AAgCD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,kBAAkB,EAC/B,wBAAwB,EAAE,6BAA6B,GACtD,IAAI,CA6DN;AA+ED,6DAA6D"}
@@ -1 +1 @@
1
- {"version":3,"file":"llms-txt-server.d.ts","sourceRoot":"","sources":["../../../../src/astro/llms-txt-server.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,kBAAkB,EAC/B,OAAO,GAAE,sBAA2B,GACnC,MAAM,GAAG,IAAI,CAqBf;AACD,gEAAgE"}
1
+ {"version":3,"file":"llms-txt-server.d.ts","sourceRoot":"","sources":["../../../src/astro/llms-txt-server.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,kBAAkB,EAC/B,OAAO,GAAE,sBAA2B,GACnC,MAAM,GAAG,IAAI,CAqBf;AACD,gEAAgE"}
@@ -1 +1 @@
1
- {"version":3,"file":"pick-labels-for-page.d.ts","sourceRoot":"","sources":["../../../../src/astro/pick-labels-for-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2DAA2D,CAAC;AACrG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,mBAAmB,EAC7B,YAAY,GAAE,SAAS,eAAe,EAAO,GAC5C,SAAS,CAkBX;AACD,qEAAqE"}
1
+ {"version":3,"file":"pick-labels-for-page.d.ts","sourceRoot":"","sources":["../../../src/astro/pick-labels-for-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2DAA2D,CAAC;AACrG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,mBAAmB,EAC7B,YAAY,GAAE,SAAS,eAAe,EAAO,GAC5C,SAAS,CAkBX;AACD,qEAAqE"}
@@ -1 +1 @@
1
- {"version":3,"file":"robots-renderer.d.ts","sourceRoot":"","sources":["../../../../src/astro/robots-renderer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,kBAAkB,GAAG,MAAM,CA+FvE;AACD,gEAAgE"}
1
+ {"version":3,"file":"robots-renderer.d.ts","sourceRoot":"","sources":["../../../src/astro/robots-renderer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,kBAAkB,GAAG,MAAM,CA+FvE;AACD,gEAAgE"}
@@ -1 +1 @@
1
- {"version":3,"file":"robots-renderer.js","sourceRoot":"","sources":["../../../../src/astro/robots-renderer.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,MAAM,UAAU,eAAe,CAAC,WAA+B;IAC7D,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,WAAW,CAAC;IAElD,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACb,qKAAqK,CACtK,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAoC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;IACtE,MAAM,MAAM,GAAwB,MAAM,EAAE,MAAM,IAAI,OAAO,CAAC;IAC9D,MAAM,eAAe,GAAG,MAAM,EAAE,eAAe,IAAI,EAAE,CAAC;IACtD,MAAM,kBAAkB,GAAG,MAAM,EAAE,kBAAkB,IAAI,EAAE,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;IAExC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B;;;OAGG;IACH,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,eAAe,GAAG,YAAY,CAAC,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACH,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,aAAa,GAAa,CAAC,eAAe,CAAC,CAAC;IAClD;;;;;;;;;;;;OAYG;IACH,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;SAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC;;;;;WAKG;QACH,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,aAAa,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtC;;;;;OAKG;IACH,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC;IAC/D,IAAI,cAAc,EAAE,CAAC;QACnB;;;;WAIG;QACH,MAAM,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,oBAAoB,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AACpC,CAAC;AACD,gEAAgE","sourcesContent":["import type {\n WebsiteRobotsConfig,\n} from '../schemas/manifests/website-root-config.shared.schemas';\n\nimport type { WebsiteSiteContext } from './website-site-context';\n\n/**\n * @wildo_source:part:start saas.website.astro.robots-renderer facet:layer:astro facet:family:website\n *\n * `renderRobotsTxt(siteContext)` — pure string builder for the\n * marketing site's `robots.txt` body. The consumer wires a thin\n * `src/pages/robots.txt.ts` Astro endpoint that imports this helper\n * + `WEBSITE_SITE_CONTEXT` and returns its output as a `Response`\n * with `Content-Type: text/plain` (see `website-seo-aeo-geo` SKILL).\n *\n * # Why a pure string builder (not an Astro component)\n *\n * Same rationale as `renderWebsitePageHeadHtml`:\n * 1. Pure TypeScript ships through the `@wildo-ai/saas-website/astro`\n * subpath barrel (Astro components do not).\n * 2. Vitest-friendly — every policy permutation is asserted\n * against the returned string without an Astro test harness.\n * 3. The Astro endpoint stays a 3-line shim the consumer can\n * audit at a glance.\n *\n * # Output shape\n *\n * The emitted text follows the de-facto `robots.txt` ordering\n * (RFC 9309 §2 + Google's published guidance):\n *\n * 1. Per-bot blocks for `allowedCrawlers` (deny-by-default\n * direction) — each named bot gets its own `User-agent: <bot>`\n * + `Allow: /` block.\n * 2. Per-bot blocks for `disallowedCrawlers` (allow-by-default\n * direction) — each named bot gets its own `User-agent: <bot>`\n * + `Disallow: /` block.\n * 3. Catch-all `User-agent: *` block carrying the site-wide\n * `policy` (`Disallow: /` if `policy === 'noindex'` OR if\n * `allowedCrawlers` is set, otherwise nothing) and any\n * `disallow[]` path-prefix entries.\n * 4. `Sitemap: <publicOrigin>/sitemap-index.xml` footer when\n * `seo.sitemap?.enabled !== false` (defaults to `true`).\n * `@astrojs/sitemap` emits `sitemap-index.xml` regardless of\n * whether the site has one or many sitemap files (the index\n * is always-present per the plugin's contract), so this is\n * the stable URL to advertise.\n *\n * # Mutual-exclusion invariant\n *\n * `WebsiteRobotsConfigSchema.superRefine` already guarantees\n * `allowedCrawlers` and `disallowedCrawlers` are NOT both set, so\n * step 1 and step 2 above are mutually exclusive at the input\n * layer. The string builder is defensive (handles both being unset)\n * but does NOT re-validate the invariant.\n *\n * # Why we always emit `Sitemap:` footer when `enabled !== false`\n *\n * The `Sitemap:` directive is independent from any `User-agent`\n * block — it is a top-level signal to any crawler that the site\n * publishes a sitemap. Even when the catch-all policy is\n * `Disallow: /` (e.g. `policy === 'noindex'`), the `Sitemap:` line\n * stays useful: a crawler that ignores `noindex` (Bing was famous\n * for this) at least has a single canonical URL list to consult,\n * and human readers of `robots.txt` see the publication contract\n * intact.\n *\n * # Failure modes\n *\n * - `siteContext.websiteConfig.publicOrigin` undefined → throws.\n * The marketing-site origin is the SINGLE source of truth for\n * absolute URL composition (see `WildoMarketingWebsiteConfig`\n * JSDoc); a missing origin is a configuration error, not a\n * silent fallback opportunity.\n *\n * @example\n * ```ts\n * // examples/<app>/website/src/pages/robots.txt.ts\n * import type { APIRoute } from 'astro';\n * import { renderRobotsTxt } from '@wildo-ai/saas-website/astro';\n * import { WEBSITE_SITE_CONTEXT } from '@/website-site-context';\n *\n * export const GET: APIRoute = () =>\n * new Response(renderRobotsTxt(WEBSITE_SITE_CONTEXT), {\n * headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n * });\n * ```\n */\nexport function renderRobotsTxt(siteContext: WebsiteSiteContext): string {\n const { rootConfig, websiteConfig } = siteContext;\n\n if (!websiteConfig.publicOrigin) {\n throw new Error(\n 'renderRobotsTxt: WildoMarketingWebsiteConfig.publicOrigin is required to compose the absolute Sitemap: URL. Author it in your service\\'s `wildo.website.config.ts`.',\n );\n }\n\n const robots: WebsiteRobotsConfig | undefined = rootConfig.seo.robots;\n const policy: 'index' | 'noindex' = robots?.policy ?? 'index';\n const allowedCrawlers = robots?.allowedCrawlers ?? [];\n const disallowedCrawlers = robots?.disallowedCrawlers ?? [];\n const disallow = robots?.disallow ?? [];\n\n const blocks: string[] = [];\n\n /**\n * Block 1 — per-bot `Allow: /` for the deny-by-default direction.\n * Empty when `allowedCrawlers` is unset (the dominant case).\n */\n for (const bot of allowedCrawlers) {\n blocks.push(`User-agent: ${bot}\\nAllow: /`);\n }\n\n /**\n * Block 2 — per-bot `Disallow: /` for the allow-by-default\n * direction. Empty when `disallowedCrawlers` is unset (the\n * dominant case for a public marketing site).\n */\n for (const bot of disallowedCrawlers) {\n blocks.push(`User-agent: ${bot}\\nDisallow: /`);\n }\n\n /**\n * Block 3 — catch-all `User-agent: *`. Two policy-driven shapes:\n * - `noindex` → `Disallow: /` (the site-wide closure).\n * - `index` (default) → `Disallow:` is the spec-canonical \"allow\n * everything\" line; combined with any per-path `Disallow: <path>`\n * entries from `disallow[]`. When `allowedCrawlers` is set, the\n * catch-all also closes the rest of the crawler universe with\n * `Disallow: /` so the named bots are the ONLY ones permitted.\n */\n const catchAllLines: string[] = ['User-agent: *'];\n /*\n * `policy === 'noindex'` deliberately does NOT emit `Disallow: /` (#494).\n *\n * `Disallow` governs CRAWLING; the `<meta name=\"robots\" content=\"noindex\">` emitted by the page-head\n * renderer governs INDEXING, and it is the one that keeps a site out of search. Barring the crawler\n * here would mean it never fetches the page and never reads that directive — so the pair defeated\n * itself, and the site stayed indexable as a bare URL. Closure is expressed in the document; this\n * file's job for that policy is to stay out of the way.\n *\n * `allowedCrawlers` is a DIFFERENT feature and keeps its `Disallow: /`: there the catch-all closes\n * the rest of the crawler universe so the named bots are the only ones permitted, which is about\n * crawling and is exactly what `Disallow` is for.\n */\n if (allowedCrawlers.length > 0) {\n catchAllLines.push('Disallow: /');\n } else if (disallow.length === 0) {\n /**\n * Spec-canonical \"allow everything\" — `Disallow:` with no path.\n * Some crawlers treat the absence of any `Disallow:` line as\n * undefined behavior; an explicit empty Disallow is the safe\n * shape.\n */\n catchAllLines.push('Disallow:');\n }\n for (const path of disallow) {\n catchAllLines.push(`Disallow: ${path}`);\n }\n blocks.push(catchAllLines.join('\\n'));\n\n /**\n * Block 4 — `Sitemap:` footer, advertised whenever sitemap\n * emission is enabled (the marketing-site default). See file\n * preamble for why we always advertise `sitemap-index.xml` as\n * the stable URL.\n */\n const sitemapEnabled = rootConfig.seo.sitemap?.enabled ?? true;\n if (sitemapEnabled) {\n /**\n * Trim trailing slash on the origin to avoid emitting\n * `https://example.com//sitemap-index.xml`. `URL` constructor\n * is overkill for a single concat; the regex is enough.\n */\n const origin = websiteConfig.publicOrigin.replace(/\\/+$/, '');\n blocks.push(`Sitemap: ${origin}/sitemap-index.xml`);\n }\n\n /**\n * Spec-conformant trailing newline. Some crawler parsers tolerate\n * its absence; emitting it is universally safe.\n */\n return `${blocks.join('\\n\\n')}\\n`;\n}\n/** @wildo_source:part:end saas.website.astro.robots-renderer */\n"]}
1
+ {"version":3,"file":"robots-renderer.js","sourceRoot":"","sources":["../../../src/astro/robots-renderer.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,MAAM,UAAU,eAAe,CAAC,WAA+B;IAC7D,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,WAAW,CAAC;IAElD,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACb,qKAAqK,CACtK,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAoC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;IACtE,MAAM,MAAM,GAAwB,MAAM,EAAE,MAAM,IAAI,OAAO,CAAC;IAC9D,MAAM,eAAe,GAAG,MAAM,EAAE,eAAe,IAAI,EAAE,CAAC;IACtD,MAAM,kBAAkB,GAAG,MAAM,EAAE,kBAAkB,IAAI,EAAE,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;IAExC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B;;;OAGG;IACH,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,eAAe,GAAG,YAAY,CAAC,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACH,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,aAAa,GAAa,CAAC,eAAe,CAAC,CAAC;IAClD;;;;;;;;;;;;OAYG;IACH,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;SAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC;;;;;WAKG;QACH,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,aAAa,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtC;;;;;OAKG;IACH,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC;IAC/D,IAAI,cAAc,EAAE,CAAC;QACnB;;;;WAIG;QACH,MAAM,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,oBAAoB,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AACpC,CAAC;AACD,gEAAgE","sourcesContent":["import type {\n WebsiteRobotsConfig,\n} from '../schemas/manifests/website-root-config.shared.schemas';\n\nimport type { WebsiteSiteContext } from './website-site-context';\n\n/**\n * @wildo_source:part:start saas.website.astro.robots-renderer facet:layer:astro facet:family:website\n *\n * `renderRobotsTxt(siteContext)` — pure string builder for the\n * marketing site's `robots.txt` body. The consumer wires a thin\n * `src/pages/robots.txt.ts` Astro endpoint that imports this helper\n * + `WEBSITE_SITE_CONTEXT` and returns its output as a `Response`\n * with `Content-Type: text/plain` (see `website-seo-aeo-geo` SKILL).\n *\n * # Why a pure string builder (not an Astro component)\n *\n * Same rationale as `renderWebsitePageHeadHtml`:\n * 1. Pure TypeScript ships through the `@wildo-ai/saas-website/astro`\n * subpath barrel (Astro components do not).\n * 2. Vitest-friendly — every policy permutation is asserted\n * against the returned string without an Astro test harness.\n * 3. The Astro endpoint stays a 3-line shim the consumer can\n * audit at a glance.\n *\n * # Output shape\n *\n * The emitted text follows the de-facto `robots.txt` ordering\n * (RFC 9309 §2 + Google's published guidance):\n *\n * 1. Per-bot blocks for `allowedCrawlers` (deny-by-default\n * direction) — each named bot gets its own `User-agent: <bot>`\n * + `Allow: /` block.\n * 2. Per-bot blocks for `disallowedCrawlers` (allow-by-default\n * direction) — each named bot gets its own `User-agent: <bot>`\n * + `Disallow: /` block.\n * 3. Catch-all `User-agent: *` block carrying the site-wide\n * `policy` (`Disallow: /` if `policy === 'noindex'` OR if\n * `allowedCrawlers` is set, otherwise nothing) and any\n * `disallow[]` path-prefix entries.\n * 4. `Sitemap: <publicOrigin>/sitemap-index.xml` footer when\n * `seo.sitemap?.enabled !== false` (defaults to `true`).\n * `@astrojs/sitemap` emits `sitemap-index.xml` regardless of\n * whether the site has one or many sitemap files (the index\n * is always-present per the plugin's contract), so this is\n * the stable URL to advertise.\n *\n * # Mutual-exclusion invariant\n *\n * `WebsiteRobotsConfigSchema.superRefine` already guarantees\n * `allowedCrawlers` and `disallowedCrawlers` are NOT both set, so\n * step 1 and step 2 above are mutually exclusive at the input\n * layer. The string builder is defensive (handles both being unset)\n * but does NOT re-validate the invariant.\n *\n * # Why we always emit `Sitemap:` footer when `enabled !== false`\n *\n * The `Sitemap:` directive is independent from any `User-agent`\n * block — it is a top-level signal to any crawler that the site\n * publishes a sitemap. Even when the catch-all policy is\n * `Disallow: /` (e.g. `policy === 'noindex'`), the `Sitemap:` line\n * stays useful: a crawler that ignores `noindex` (Bing was famous\n * for this) at least has a single canonical URL list to consult,\n * and human readers of `robots.txt` see the publication contract\n * intact.\n *\n * # Failure modes\n *\n * - `siteContext.websiteConfig.publicOrigin` undefined → throws.\n * The marketing-site origin is the SINGLE source of truth for\n * absolute URL composition (see `WildoMarketingWebsiteConfig`\n * JSDoc); a missing origin is a configuration error, not a\n * silent fallback opportunity.\n *\n * @example\n * ```ts\n * // examples/<app>/website/src/pages/robots.txt.ts\n * import type { APIRoute } from 'astro';\n * import { renderRobotsTxt } from '@wildo-ai/saas-website/astro';\n * import { WEBSITE_SITE_CONTEXT } from '@/website-site-context';\n *\n * export const GET: APIRoute = () =>\n * new Response(renderRobotsTxt(WEBSITE_SITE_CONTEXT), {\n * headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n * });\n * ```\n */\nexport function renderRobotsTxt(siteContext: WebsiteSiteContext): string {\n const { rootConfig, websiteConfig } = siteContext;\n\n if (!websiteConfig.publicOrigin) {\n throw new Error(\n 'renderRobotsTxt: WildoMarketingWebsiteConfig.publicOrigin is required to compose the absolute Sitemap: URL. Author it in your service\\'s `wildo.website.config.ts`.',\n );\n }\n\n const robots: WebsiteRobotsConfig | undefined = rootConfig.seo.robots;\n const policy: 'index' | 'noindex' = robots?.policy ?? 'index';\n const allowedCrawlers = robots?.allowedCrawlers ?? [];\n const disallowedCrawlers = robots?.disallowedCrawlers ?? [];\n const disallow = robots?.disallow ?? [];\n\n const blocks: string[] = [];\n\n /**\n * Block 1 — per-bot `Allow: /` for the deny-by-default direction.\n * Empty when `allowedCrawlers` is unset (the dominant case).\n */\n for (const bot of allowedCrawlers) {\n blocks.push(`User-agent: ${bot}\\nAllow: /`);\n }\n\n /**\n * Block 2 — per-bot `Disallow: /` for the allow-by-default\n * direction. Empty when `disallowedCrawlers` is unset (the\n * dominant case for a public marketing site).\n */\n for (const bot of disallowedCrawlers) {\n blocks.push(`User-agent: ${bot}\\nDisallow: /`);\n }\n\n /**\n * Block 3 — catch-all `User-agent: *`. Two policy-driven shapes:\n * - `noindex` → `Disallow: /` (the site-wide closure).\n * - `index` (default) → `Disallow:` is the spec-canonical \"allow\n * everything\" line; combined with any per-path `Disallow: <path>`\n * entries from `disallow[]`. When `allowedCrawlers` is set, the\n * catch-all also closes the rest of the crawler universe with\n * `Disallow: /` so the named bots are the ONLY ones permitted.\n */\n const catchAllLines: string[] = ['User-agent: *'];\n /*\n * `policy === 'noindex'` deliberately does NOT emit `Disallow: /` (#494).\n *\n * `Disallow` governs CRAWLING; the `<meta name=\"robots\" content=\"noindex\">` emitted by the page-head\n * renderer governs INDEXING, and it is the one that keeps a site out of search. Barring the crawler\n * here would mean it never fetches the page and never reads that directive — so the pair defeated\n * itself, and the site stayed indexable as a bare URL. Closure is expressed in the document; this\n * file's job for that policy is to stay out of the way.\n *\n * `allowedCrawlers` is a DIFFERENT feature and keeps its `Disallow: /`: there the catch-all closes\n * the rest of the crawler universe so the named bots are the only ones permitted, which is about\n * crawling and is exactly what `Disallow` is for.\n */\n if (allowedCrawlers.length > 0) {\n catchAllLines.push('Disallow: /');\n } else if (disallow.length === 0) {\n /**\n * Spec-canonical \"allow everything\" — `Disallow:` with no path.\n * Some crawlers treat the absence of any `Disallow:` line as\n * undefined behavior; an explicit empty Disallow is the safe\n * shape.\n */\n catchAllLines.push('Disallow:');\n }\n for (const path of disallow) {\n catchAllLines.push(`Disallow: ${path}`);\n }\n blocks.push(catchAllLines.join('\\n'));\n\n /**\n * Block 4 — `Sitemap:` footer, advertised whenever sitemap\n * emission is enabled (the marketing-site default). See file\n * preamble for why we always advertise `sitemap-index.xml` as\n * the stable URL.\n */\n const sitemapEnabled = rootConfig.seo.sitemap?.enabled ?? true;\n if (sitemapEnabled) {\n /**\n * Trim trailing slash on the origin to avoid emitting\n * `https://example.com//sitemap-index.xml`. `URL` constructor\n * is overkill for a single concat; the regex is enough.\n */\n const origin = websiteConfig.publicOrigin.replace(/\\/+$/, '');\n blocks.push(`Sitemap: ${origin}/sitemap-index.xml`);\n }\n\n /**\n * Spec-conformant trailing newline. Some crawler parsers tolerate\n * its absence; emitting it is universally safe.\n */\n return `${blocks.join('\\n\\n')}\\n`;\n}\n/** @wildo_source:part:end saas.website.astro.robots-renderer */\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"sitemap-coverage.d.ts","sourceRoot":"","sources":["../../../../src/astro/sitemap-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAK9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AACH,MAAM,WAAW,yBAAyB;IACxC,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrF;AAED,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,kBAAkB,GAC9B,SAAS,yBAAyB,EAAE,CAiFtC;AACD,iEAAiE"}
1
+ {"version":3,"file":"sitemap-coverage.d.ts","sourceRoot":"","sources":["../../../src/astro/sitemap-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAK9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AACH,MAAM,WAAW,yBAAyB;IACxC,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrF;AAED,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,kBAAkB,GAC9B,SAAS,yBAAyB,EAAE,CAiFtC;AACD,iEAAiE"}
@@ -1 +1 @@
1
- {"version":3,"file":"structured-data.renderer.d.ts","sourceRoot":"","sources":["../../../../src/astro/structured-data.renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAE7B,MAAM,mEAAmE,CAAC;AAC3E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+DAA+D,CAAC;AAgD9G,MAAM,WAAW,+BAA+B;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,IAAI,CAAC,wBAAwB,EAAE,YAAY,GAAG,mBAAmB,CAAC,EAAE,CAAC;IACzF;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;CACxD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,+BAA+B,GAAG,MAAM,CAiDtF;AAoDD,yEAAyE"}
1
+ {"version":3,"file":"structured-data.renderer.d.ts","sourceRoot":"","sources":["../../../src/astro/structured-data.renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAE7B,MAAM,mEAAmE,CAAC;AAC3E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+DAA+D,CAAC;AAgD9G,MAAM,WAAW,+BAA+B;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,IAAI,CAAC,wBAAwB,EAAE,YAAY,GAAG,mBAAmB,CAAC,EAAE,CAAC;IACzF;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;CACxD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,+BAA+B,GAAG,MAAM,CAiDtF;AAoDD,yEAAyE"}
@@ -1 +1 @@
1
- {"version":3,"file":"website-page-head.renderer.d.ts","sourceRoot":"","sources":["../../../../src/astro/website-page-head.renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAG9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+DAA+D,CAAC;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2DAA2D,CAAC;AACrG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAG5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B;;;;;OAKG;IACH,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,gCAAgC,GAAG,MAAM,CAuLxF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAehF;AAED;;;;;;;;GAQG"}
1
+ {"version":3,"file":"website-page-head.renderer.d.ts","sourceRoot":"","sources":["../../../src/astro/website-page-head.renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAG9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+DAA+D,CAAC;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2DAA2D,CAAC;AACrG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAG5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B;;;;;OAKG;IACH,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,gCAAgC,GAAG,MAAM,CAuLxF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAehF;AAED;;;;;;;;GAQG"}
@@ -1 +1 @@
1
- {"version":3,"file":"website-page-head.renderer.js","sourceRoot":"","sources":["../../../../src/astro/website-page-head.renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';\n\nimport { buildLocalizedRoutePath } from '../core/routing/internal-routing.utils';\nimport type { WebsiteDesignTokens } from '../schemas/design-tokens/website-design-tokens.shared.schemas';\nimport type { WebsitePageManifest } from '../schemas/manifests/website-page-manifest.shared.schemas';\nimport type { LabelPack } from '../schemas/validators/label-pack.validator';\n\nimport { escapeHtmlAttribute, escapeHtmlText } from './internal/html-escape';\nimport type { WebsiteSiteContext } from './website-site-context';\n\n/**\n * @wildo_source:part:start saas.website.astro.head-renderer facet:layer:astro facet:family:website\n *\n * Head-block renderers — pure string builders the consumer's per-page\n * `.astro` file injects via `<Fragment set:html={...}/>` /\n * `<style set:html={...}></style>`. Two functions:\n *\n * - `renderWebsitePageHeadHtml(opts)` — emits the complete SEO\n * `<head>` block: `<title>`, meta description, full Open Graph\n * card (`og:title` / `og:description` / `og:type` / `og:url` /\n * `og:site_name` / `og:locale` / `og:locale:alternate` / optional\n * `og:image`), Twitter card mirrors, `<link rel=\"canonical\">`,\n * and one `<link rel=\"alternate\" hreflang>` per declared locale\n * (plus an `x-default` for Google's i18n discoverability). Every\n * URL is ABSOLUTE (composed from `websiteConfig.publicOrigin` +\n * the page's `routePath`) — relative hreflang/canonical\n * annotations are not honored consistently across crawlers\n * (Phase 6 audit findings H-B / H-C / M-A).\n * - `renderWebsiteDesignTokensCss(tokens)` — flattens the design-token\n * bundle into `--website-*` custom properties scoped to `:root`.\n * Server-static — zero island JS.\n *\n * **Why pure string builders** (rather than React components or Astro\n * components):\n *\n * 1. **Avoids the `.astro` distribution problem.** A `.astro` shell\n * cannot be re-exported from a TS subpath barrel and `tsc` does\n * not copy `.astro` files to `dist/`. Pure TS sidesteps both.\n * 2. **Avoids the React-island boundary.** Rendering head content\n * via React would require either (a) a server-only React subtree\n * (extra moving part) or (b) hydrating the `<head>` on the client\n * (waste of bundle size for static-build content).\n * 3. **Vitest-friendly.** Pure functions returning strings are\n * trivially asserted against without an Astro test harness.\n *\n * **HTML escaping**: every consumer-supplied string (title,\n * description, OG image URL, hreflang values) is escaped with\n * `escapeHtmlAttribute` / `escapeHtmlText` before interpolation into\n * the emitted markup. Marketing copy frequently contains characters\n * (quotes, ampersands, the rare `<`) that would break the surrounding\n * tag if interpolated raw — escaping is non-negotiable for a public\n * surface.\n *\n * **Failure modes** — `renderWebsitePageHeadHtml` throws when:\n * - `manifest.metaLabelKeys.titleKey` is absent from the pack\n * - `manifest.metaLabelKeys.descriptionKey` is absent from the pack\n * Both throw with the locale + key + actionable next step (`Run\n * \\`wildo website audit\\` or add the entry to <pack-path>.json`).\n */\n\nexport interface RenderWebsitePageHeadHtmlOptions {\n manifest: WebsitePageManifest;\n /**\n * Composed `WebsiteSiteContext` — the renderer reads\n * `websiteConfig.{defaultLocale, locales, publicOrigin}` for the\n * URL/locale surface and `rootConfig.seo.{siteName, defaultOgImageUrl}`\n * for the SEO branding fallback.\n */\n siteContext: WebsiteSiteContext;\n locale: AvailableLanguage;\n labelPack: LabelPack;\n}\n\nexport function renderWebsitePageHeadHtml(opts: RenderWebsitePageHeadHtmlOptions): string {\n const { manifest, siteContext, locale, labelPack } = opts;\n const { rootConfig, websiteConfig } = siteContext;\n\n const titleKey = manifest.metaLabelKeys.titleKey as unknown as string;\n const descriptionKey = manifest.metaLabelKeys.descriptionKey as unknown as string;\n const title = labelPack[titleKey];\n const description = labelPack[descriptionKey];\n\n if (title === undefined) {\n throw new Error(\n `[renderWebsitePageHeadHtml] Label pack for locale \"${locale}\" is missing ` +\n `the page title key \"${titleKey}\" (page ref=\"${manifest.ref as unknown as string}\"). ` +\n `Run \\`wildo website audit\\` or add the entry to your <locale>.json pack.`,\n );\n }\n if (description === undefined) {\n throw new Error(\n `[renderWebsitePageHeadHtml] Label pack for locale \"${locale}\" is missing ` +\n `the page description key \"${descriptionKey}\" (page ref=\"${manifest.ref as unknown as string}\"). ` +\n `Run \\`wildo website audit\\` or add the entry to your <locale>.json pack.`,\n );\n }\n\n /**\n * OG image precedence: per-page `manifest.metaLabelKeys.ogImageUrl`\n * wins; falls back to the site-level `seo.defaultOgImageUrl` so\n * marketing pages without a hero image still produce a richer\n * social-card (Phase 6 audit fix M-A). When neither is present,\n * the Twitter card kind degrades to the smaller `summary` and the\n * `og:image` / `twitter:image` lines are omitted entirely.\n */\n const ogImageUrl = manifest.metaLabelKeys.ogImageUrl ?? rootConfig.seo.defaultOgImageUrl;\n const titleAttr = escapeHtmlAttribute(title);\n const descriptionAttr = escapeHtmlAttribute(description);\n const titleText = escapeHtmlText(title);\n\n /**\n * Absolute URL builder. `prefixDefaultLocale: false` means the\n * default locale lives at the locale-neutral path; every other\n * locale sits under `/<locale>/<routePath>`. `x-default` always\n * resolves to the default-locale path.\n *\n * Every URL emitted here is FULLY-QUALIFIED (composed against\n * `websiteConfig.publicOrigin`) — Google's hreflang spec requires\n * absolute URLs, and `<link rel=\"canonical\">` relies on absolute\n * URLs to survive cross-host fetches (preview deployments, CDN\n * edges). See `WildoMarketingWebsiteConfigSchema.publicOrigin`\n * JSDoc for the full rationale (incl. trailing-slash rejection).\n */\n const routePath = manifest.routePath as unknown as string;\n const siteOrigin = websiteConfig.publicOrigin;\n const defaultLocale = websiteConfig.defaultLocale;\n const currentLocaleStr = String(locale);\n\n /**\n * Compose the absolute URL for `(locale, routePath)` by delegating\n * the locale-prefix decision to the shared `buildLocalizedRoutePath`\n * helper — same routing rule that powers `WebsiteInternalLink`. This\n * guarantees that hreflang/canonical URLs and the chrome's internal\n * links can never disagree about how a locale is prefixed.\n */\n function buildAbsoluteUrl(forLocale: AvailableLanguage): string {\n const path = buildLocalizedRoutePath({\n locale: forLocale,\n defaultLocale,\n routePath,\n });\n return `${siteOrigin}${path}`;\n }\n\n const canonicalUrl = buildAbsoluteUrl(locale);\n\n const hreflangLines: string[] = [];\n for (const entry of websiteConfig.locales) {\n const localeStr = String(entry.locale);\n hreflangLines.push(\n `<link rel=\"alternate\" hreflang=\"${escapeHtmlAttribute(localeStr)}\" href=\"${escapeHtmlAttribute(buildAbsoluteUrl(entry.locale))}\" />`,\n );\n }\n hreflangLines.push(\n `<link rel=\"alternate\" hreflang=\"x-default\" href=\"${escapeHtmlAttribute(buildAbsoluteUrl(defaultLocale))}\" />`,\n );\n\n /**\n * `og:image` + `twitter:image` are emitted only when an image URL\n * is available (page-level override OR site-level fallback).\n * Twitter card type also flips between `summary` (no image) and\n * `summary_large_image` (image present).\n */\n const ogImageLines: string[] = [];\n if (ogImageUrl !== undefined) {\n const ogImageAttr = escapeHtmlAttribute(ogImageUrl);\n ogImageLines.push(\n `<meta property=\"og:image\" content=\"${ogImageAttr}\" />`,\n `<meta name=\"twitter:image\" content=\"${ogImageAttr}\" />`,\n );\n }\n const twitterCardKind = ogImageUrl !== undefined ? 'summary_large_image' : 'summary';\n\n /**\n * `og:locale:alternate` — one per non-current declared locale. Open\n * Graph spec: the `og:locale` field carries the page's primary\n * locale; alternates declare the other locales the page is\n * available in. Emitted in declaration order.\n *\n * Locale format: we emit the bare language code (`en`, `fr`) per\n * the AvailableLanguage atom shape. Open Graph technically\n * recommends `language_TERRITORY` (e.g. `en_US`), but Facebook /\n * LinkedIn / Slack accept the bare language code in practice. The\n * future fix when the platform grows territory-tagged locales is to\n * map at this site (no consumer change required).\n */\n const ogLocaleAlternateLines: string[] = [];\n for (const entry of websiteConfig.locales) {\n const localeStr = String(entry.locale);\n if (localeStr === currentLocaleStr) continue;\n ogLocaleAlternateLines.push(\n `<meta property=\"og:locale:alternate\" content=\"${escapeHtmlAttribute(localeStr)}\" />`,\n );\n }\n\n const siteNameAttr = escapeHtmlAttribute(rootConfig.seo.siteName);\n const canonicalAttr = escapeHtmlAttribute(canonicalUrl);\n const ogLocaleAttr = escapeHtmlAttribute(currentLocaleStr);\n\n /**\n * SITE-WIDE `noindex` (#494) — the directive that actually keeps a site out of search.\n *\n * `robots.txt` `Disallow` governs CRAWLING, not INDEXING: a disallowed URL can still be listed, as a\n * bare URL with no snippet, if anything links to it. Only this directive de-indexes. Until 2026-09-08\n * a site declared `noindex` emitted the `Disallow` and NOT this, so it was closed to well-behaved\n * crawlers and still indexable — the weaker half of the pair.\n *\n * The two are also mutually defeating, which is why `renderRobotsTxt` no longer emits `Disallow: /`\n * for this policy: a crawler barred from fetching the page never reads the directive telling it not\n * to index. To stay out of search you must let the crawler IN and tell it no.\n *\n * `noindex` only — not `noindex, nofollow`. `nofollow` additionally suppresses link discovery, which\n * is a broader claim than \"keep this out of the index\" and is not what the policy declares.\n */\n const robotsDirectives: string[] = [];\n if (rootConfig.seo.robots?.policy === 'noindex') {\n robotsDirectives.push('noindex');\n }\n /**\n * AI-training opt-out (D-AG3) — emitted ONLY when the page manifest opts in via\n * `seo.noaiOptOut: true`. Default is OPT-IN to AI training (the marketing-site default). This\n * emission pairs with the sibling `_headers` entry produced by `renderWebsitePageNoaiHeaders()`\n * for crawlers that don't honor in-document meta.\n *\n * `noai` (block AI training on text) and `noimageai` (block AI training on images) are the two\n * directives the major AI crawlers (GPTBot, ClaudeBot, Google-Extended, etc.) recognise.\n */\n if (manifest.seo?.noaiOptOut === true) {\n robotsDirectives.push('noai', 'noimageai');\n }\n /*\n * ONE `<meta name=\"robots\">`, carrying every directive comma-separated — the canonical shape. Two\n * separate robots meta tags are legal and are read inconsistently; merging avoids the question.\n */\n const noaiMetaLines: string[] = robotsDirectives.length > 0\n ? [`<meta name=\"robots\" content=\"${robotsDirectives.join(', ')}\" />`]\n : [];\n\n return [\n `<title>${titleText}</title>`,\n `<meta name=\"description\" content=\"${descriptionAttr}\" />`,\n `<link rel=\"canonical\" href=\"${canonicalAttr}\" />`,\n `<meta property=\"og:title\" content=\"${titleAttr}\" />`,\n `<meta property=\"og:description\" content=\"${descriptionAttr}\" />`,\n `<meta property=\"og:type\" content=\"website\" />`,\n `<meta property=\"og:url\" content=\"${canonicalAttr}\" />`,\n `<meta property=\"og:site_name\" content=\"${siteNameAttr}\" />`,\n `<meta property=\"og:locale\" content=\"${ogLocaleAttr}\" />`,\n ...ogLocaleAlternateLines,\n ...ogImageLines,\n `<meta name=\"twitter:card\" content=\"${twitterCardKind}\" />`,\n `<meta name=\"twitter:title\" content=\"${titleAttr}\" />`,\n `<meta name=\"twitter:description\" content=\"${descriptionAttr}\" />`,\n ...noaiMetaLines,\n ...hreflangLines,\n ].join('\\n');\n}\n\n/**\n * Flatten `WebsiteDesignTokens` to a `:root { … }` block of CSS custom\n * properties. Naming convention: `--website-<group>-<token>` for nested\n * groups (`colors.primary` → `--website-colors-primary`); top-level\n * string-valued tokens (none today, future-proofed) emit as\n * `--website-<token>`.\n *\n * **Why scoped to `:root`** rather than `<WebsitePageLayout>`'s root\n * div: marketing pages frequently embed third-party widgets (live-chat,\n * analytics overlays) that paint outside the React tree. Scoping\n * tokens to `:root` makes them visible to those widgets too. The\n * design-token surface is small enough that the cost of a broader\n * scope (token-name collisions with consumer-authored `:root` rules)\n * is bounded by the `--website-` prefix.\n */\nexport function renderWebsiteDesignTokensCss(tokens: WebsiteDesignTokens): string {\n const lines: string[] = [':root {'];\n for (const [groupName, groupValue] of Object.entries(tokens) as [string, unknown][]) {\n if (groupValue !== null && typeof groupValue === 'object' && !Array.isArray(groupValue)) {\n for (const [tokenName, tokenValue] of Object.entries(groupValue) as [string, unknown][]) {\n if (typeof tokenValue === 'string') {\n lines.push(` --website-${groupName}-${tokenName}: ${tokenValue};`);\n }\n }\n } else if (typeof groupValue === 'string') {\n lines.push(` --website-${groupName}: ${groupValue};`);\n }\n }\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * @wildo_source:part:end saas.website.astro.head-renderer\n *\n * HTML escape helpers moved to `./internal/html-escape.ts` (Phase 7)\n * so the new `blog-post-head.renderer.ts` sibling can share the same\n * escape contract instead of redefining it. See that module's preamble\n * for the framework-mindset rationale (one escape contract per engine,\n * not one per renderer).\n */\n"]}
1
+ {"version":3,"file":"website-page-head.renderer.js","sourceRoot":"","sources":["../../../src/astro/website-page-head.renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';\n\nimport { buildLocalizedRoutePath } from '../core/routing/internal-routing.utils';\nimport type { WebsiteDesignTokens } from '../schemas/design-tokens/website-design-tokens.shared.schemas';\nimport type { WebsitePageManifest } from '../schemas/manifests/website-page-manifest.shared.schemas';\nimport type { LabelPack } from '../schemas/validators/label-pack.validator';\n\nimport { escapeHtmlAttribute, escapeHtmlText } from './internal/html-escape';\nimport type { WebsiteSiteContext } from './website-site-context';\n\n/**\n * @wildo_source:part:start saas.website.astro.head-renderer facet:layer:astro facet:family:website\n *\n * Head-block renderers — pure string builders the consumer's per-page\n * `.astro` file injects via `<Fragment set:html={...}/>` /\n * `<style set:html={...}></style>`. Two functions:\n *\n * - `renderWebsitePageHeadHtml(opts)` — emits the complete SEO\n * `<head>` block: `<title>`, meta description, full Open Graph\n * card (`og:title` / `og:description` / `og:type` / `og:url` /\n * `og:site_name` / `og:locale` / `og:locale:alternate` / optional\n * `og:image`), Twitter card mirrors, `<link rel=\"canonical\">`,\n * and one `<link rel=\"alternate\" hreflang>` per declared locale\n * (plus an `x-default` for Google's i18n discoverability). Every\n * URL is ABSOLUTE (composed from `websiteConfig.publicOrigin` +\n * the page's `routePath`) — relative hreflang/canonical\n * annotations are not honored consistently across crawlers\n * (Phase 6 audit findings H-B / H-C / M-A).\n * - `renderWebsiteDesignTokensCss(tokens)` — flattens the design-token\n * bundle into `--website-*` custom properties scoped to `:root`.\n * Server-static — zero island JS.\n *\n * **Why pure string builders** (rather than React components or Astro\n * components):\n *\n * 1. **Avoids the `.astro` distribution problem.** A `.astro` shell\n * cannot be re-exported from a TS subpath barrel and `tsc` does\n * not copy `.astro` files to `dist/`. Pure TS sidesteps both.\n * 2. **Avoids the React-island boundary.** Rendering head content\n * via React would require either (a) a server-only React subtree\n * (extra moving part) or (b) hydrating the `<head>` on the client\n * (waste of bundle size for static-build content).\n * 3. **Vitest-friendly.** Pure functions returning strings are\n * trivially asserted against without an Astro test harness.\n *\n * **HTML escaping**: every consumer-supplied string (title,\n * description, OG image URL, hreflang values) is escaped with\n * `escapeHtmlAttribute` / `escapeHtmlText` before interpolation into\n * the emitted markup. Marketing copy frequently contains characters\n * (quotes, ampersands, the rare `<`) that would break the surrounding\n * tag if interpolated raw — escaping is non-negotiable for a public\n * surface.\n *\n * **Failure modes** — `renderWebsitePageHeadHtml` throws when:\n * - `manifest.metaLabelKeys.titleKey` is absent from the pack\n * - `manifest.metaLabelKeys.descriptionKey` is absent from the pack\n * Both throw with the locale + key + actionable next step (`Run\n * \\`wildo website audit\\` or add the entry to <pack-path>.json`).\n */\n\nexport interface RenderWebsitePageHeadHtmlOptions {\n manifest: WebsitePageManifest;\n /**\n * Composed `WebsiteSiteContext` — the renderer reads\n * `websiteConfig.{defaultLocale, locales, publicOrigin}` for the\n * URL/locale surface and `rootConfig.seo.{siteName, defaultOgImageUrl}`\n * for the SEO branding fallback.\n */\n siteContext: WebsiteSiteContext;\n locale: AvailableLanguage;\n labelPack: LabelPack;\n}\n\nexport function renderWebsitePageHeadHtml(opts: RenderWebsitePageHeadHtmlOptions): string {\n const { manifest, siteContext, locale, labelPack } = opts;\n const { rootConfig, websiteConfig } = siteContext;\n\n const titleKey = manifest.metaLabelKeys.titleKey as unknown as string;\n const descriptionKey = manifest.metaLabelKeys.descriptionKey as unknown as string;\n const title = labelPack[titleKey];\n const description = labelPack[descriptionKey];\n\n if (title === undefined) {\n throw new Error(\n `[renderWebsitePageHeadHtml] Label pack for locale \"${locale}\" is missing ` +\n `the page title key \"${titleKey}\" (page ref=\"${manifest.ref as unknown as string}\"). ` +\n `Run \\`wildo website audit\\` or add the entry to your <locale>.json pack.`,\n );\n }\n if (description === undefined) {\n throw new Error(\n `[renderWebsitePageHeadHtml] Label pack for locale \"${locale}\" is missing ` +\n `the page description key \"${descriptionKey}\" (page ref=\"${manifest.ref as unknown as string}\"). ` +\n `Run \\`wildo website audit\\` or add the entry to your <locale>.json pack.`,\n );\n }\n\n /**\n * OG image precedence: per-page `manifest.metaLabelKeys.ogImageUrl`\n * wins; falls back to the site-level `seo.defaultOgImageUrl` so\n * marketing pages without a hero image still produce a richer\n * social-card (Phase 6 audit fix M-A). When neither is present,\n * the Twitter card kind degrades to the smaller `summary` and the\n * `og:image` / `twitter:image` lines are omitted entirely.\n */\n const ogImageUrl = manifest.metaLabelKeys.ogImageUrl ?? rootConfig.seo.defaultOgImageUrl;\n const titleAttr = escapeHtmlAttribute(title);\n const descriptionAttr = escapeHtmlAttribute(description);\n const titleText = escapeHtmlText(title);\n\n /**\n * Absolute URL builder. `prefixDefaultLocale: false` means the\n * default locale lives at the locale-neutral path; every other\n * locale sits under `/<locale>/<routePath>`. `x-default` always\n * resolves to the default-locale path.\n *\n * Every URL emitted here is FULLY-QUALIFIED (composed against\n * `websiteConfig.publicOrigin`) — Google's hreflang spec requires\n * absolute URLs, and `<link rel=\"canonical\">` relies on absolute\n * URLs to survive cross-host fetches (preview deployments, CDN\n * edges). See `WildoMarketingWebsiteConfigSchema.publicOrigin`\n * JSDoc for the full rationale (incl. trailing-slash rejection).\n */\n const routePath = manifest.routePath as unknown as string;\n const siteOrigin = websiteConfig.publicOrigin;\n const defaultLocale = websiteConfig.defaultLocale;\n const currentLocaleStr = String(locale);\n\n /**\n * Compose the absolute URL for `(locale, routePath)` by delegating\n * the locale-prefix decision to the shared `buildLocalizedRoutePath`\n * helper — same routing rule that powers `WebsiteInternalLink`. This\n * guarantees that hreflang/canonical URLs and the chrome's internal\n * links can never disagree about how a locale is prefixed.\n */\n function buildAbsoluteUrl(forLocale: AvailableLanguage): string {\n const path = buildLocalizedRoutePath({\n locale: forLocale,\n defaultLocale,\n routePath,\n });\n return `${siteOrigin}${path}`;\n }\n\n const canonicalUrl = buildAbsoluteUrl(locale);\n\n const hreflangLines: string[] = [];\n for (const entry of websiteConfig.locales) {\n const localeStr = String(entry.locale);\n hreflangLines.push(\n `<link rel=\"alternate\" hreflang=\"${escapeHtmlAttribute(localeStr)}\" href=\"${escapeHtmlAttribute(buildAbsoluteUrl(entry.locale))}\" />`,\n );\n }\n hreflangLines.push(\n `<link rel=\"alternate\" hreflang=\"x-default\" href=\"${escapeHtmlAttribute(buildAbsoluteUrl(defaultLocale))}\" />`,\n );\n\n /**\n * `og:image` + `twitter:image` are emitted only when an image URL\n * is available (page-level override OR site-level fallback).\n * Twitter card type also flips between `summary` (no image) and\n * `summary_large_image` (image present).\n */\n const ogImageLines: string[] = [];\n if (ogImageUrl !== undefined) {\n const ogImageAttr = escapeHtmlAttribute(ogImageUrl);\n ogImageLines.push(\n `<meta property=\"og:image\" content=\"${ogImageAttr}\" />`,\n `<meta name=\"twitter:image\" content=\"${ogImageAttr}\" />`,\n );\n }\n const twitterCardKind = ogImageUrl !== undefined ? 'summary_large_image' : 'summary';\n\n /**\n * `og:locale:alternate` — one per non-current declared locale. Open\n * Graph spec: the `og:locale` field carries the page's primary\n * locale; alternates declare the other locales the page is\n * available in. Emitted in declaration order.\n *\n * Locale format: we emit the bare language code (`en`, `fr`) per\n * the AvailableLanguage atom shape. Open Graph technically\n * recommends `language_TERRITORY` (e.g. `en_US`), but Facebook /\n * LinkedIn / Slack accept the bare language code in practice. The\n * future fix when the platform grows territory-tagged locales is to\n * map at this site (no consumer change required).\n */\n const ogLocaleAlternateLines: string[] = [];\n for (const entry of websiteConfig.locales) {\n const localeStr = String(entry.locale);\n if (localeStr === currentLocaleStr) continue;\n ogLocaleAlternateLines.push(\n `<meta property=\"og:locale:alternate\" content=\"${escapeHtmlAttribute(localeStr)}\" />`,\n );\n }\n\n const siteNameAttr = escapeHtmlAttribute(rootConfig.seo.siteName);\n const canonicalAttr = escapeHtmlAttribute(canonicalUrl);\n const ogLocaleAttr = escapeHtmlAttribute(currentLocaleStr);\n\n /**\n * SITE-WIDE `noindex` (#494) — the directive that actually keeps a site out of search.\n *\n * `robots.txt` `Disallow` governs CRAWLING, not INDEXING: a disallowed URL can still be listed, as a\n * bare URL with no snippet, if anything links to it. Only this directive de-indexes. Until 2026-09-08\n * a site declared `noindex` emitted the `Disallow` and NOT this, so it was closed to well-behaved\n * crawlers and still indexable — the weaker half of the pair.\n *\n * The two are also mutually defeating, which is why `renderRobotsTxt` no longer emits `Disallow: /`\n * for this policy: a crawler barred from fetching the page never reads the directive telling it not\n * to index. To stay out of search you must let the crawler IN and tell it no.\n *\n * `noindex` only — not `noindex, nofollow`. `nofollow` additionally suppresses link discovery, which\n * is a broader claim than \"keep this out of the index\" and is not what the policy declares.\n */\n const robotsDirectives: string[] = [];\n if (rootConfig.seo.robots?.policy === 'noindex') {\n robotsDirectives.push('noindex');\n }\n /**\n * AI-training opt-out (D-AG3) — emitted ONLY when the page manifest opts in via\n * `seo.noaiOptOut: true`. Default is OPT-IN to AI training (the marketing-site default). This\n * emission pairs with the sibling `_headers` entry produced by `renderWebsitePageNoaiHeaders()`\n * for crawlers that don't honor in-document meta.\n *\n * `noai` (block AI training on text) and `noimageai` (block AI training on images) are the two\n * directives the major AI crawlers (GPTBot, ClaudeBot, Google-Extended, etc.) recognise.\n */\n if (manifest.seo?.noaiOptOut === true) {\n robotsDirectives.push('noai', 'noimageai');\n }\n /*\n * ONE `<meta name=\"robots\">`, carrying every directive comma-separated — the canonical shape. Two\n * separate robots meta tags are legal and are read inconsistently; merging avoids the question.\n */\n const noaiMetaLines: string[] = robotsDirectives.length > 0\n ? [`<meta name=\"robots\" content=\"${robotsDirectives.join(', ')}\" />`]\n : [];\n\n return [\n `<title>${titleText}</title>`,\n `<meta name=\"description\" content=\"${descriptionAttr}\" />`,\n `<link rel=\"canonical\" href=\"${canonicalAttr}\" />`,\n `<meta property=\"og:title\" content=\"${titleAttr}\" />`,\n `<meta property=\"og:description\" content=\"${descriptionAttr}\" />`,\n `<meta property=\"og:type\" content=\"website\" />`,\n `<meta property=\"og:url\" content=\"${canonicalAttr}\" />`,\n `<meta property=\"og:site_name\" content=\"${siteNameAttr}\" />`,\n `<meta property=\"og:locale\" content=\"${ogLocaleAttr}\" />`,\n ...ogLocaleAlternateLines,\n ...ogImageLines,\n `<meta name=\"twitter:card\" content=\"${twitterCardKind}\" />`,\n `<meta name=\"twitter:title\" content=\"${titleAttr}\" />`,\n `<meta name=\"twitter:description\" content=\"${descriptionAttr}\" />`,\n ...noaiMetaLines,\n ...hreflangLines,\n ].join('\\n');\n}\n\n/**\n * Flatten `WebsiteDesignTokens` to a `:root { … }` block of CSS custom\n * properties. Naming convention: `--website-<group>-<token>` for nested\n * groups (`colors.primary` → `--website-colors-primary`); top-level\n * string-valued tokens (none today, future-proofed) emit as\n * `--website-<token>`.\n *\n * **Why scoped to `:root`** rather than `<WebsitePageLayout>`'s root\n * div: marketing pages frequently embed third-party widgets (live-chat,\n * analytics overlays) that paint outside the React tree. Scoping\n * tokens to `:root` makes them visible to those widgets too. The\n * design-token surface is small enough that the cost of a broader\n * scope (token-name collisions with consumer-authored `:root` rules)\n * is bounded by the `--website-` prefix.\n */\nexport function renderWebsiteDesignTokensCss(tokens: WebsiteDesignTokens): string {\n const lines: string[] = [':root {'];\n for (const [groupName, groupValue] of Object.entries(tokens) as [string, unknown][]) {\n if (groupValue !== null && typeof groupValue === 'object' && !Array.isArray(groupValue)) {\n for (const [tokenName, tokenValue] of Object.entries(groupValue) as [string, unknown][]) {\n if (typeof tokenValue === 'string') {\n lines.push(` --website-${groupName}-${tokenName}: ${tokenValue};`);\n }\n }\n } else if (typeof groupValue === 'string') {\n lines.push(` --website-${groupName}: ${groupValue};`);\n }\n }\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * @wildo_source:part:end saas.website.astro.head-renderer\n *\n * HTML escape helpers moved to `./internal/html-escape.ts` (Phase 7)\n * so the new `blog-post-head.renderer.ts` sibling can share the same\n * escape contract instead of redefining it. See that module's preamble\n * for the framework-mindset rationale (one escape contract per engine,\n * not one per renderer).\n */\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"website-page-runtime.helper.d.ts","sourceRoot":"","sources":["../../../../src/astro/website-page-runtime.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAGzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2DAA2D,CAAC;AACrG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAI5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,gFAAgF;IAChF,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,yEAAyE;IACzE,WAAW,EAAE,kBAAkB,CAAC;IAChC,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;;;;;OAQG;IACH,aAAa,EAAE,iBAAiB,CAAC;IACjC,qEAAqE;IACrE,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,6BAA6B,GAClC,kBAAkB,CAqCpB;AA+BD,+DAA+D"}
1
+ {"version":3,"file":"website-page-runtime.helper.d.ts","sourceRoot":"","sources":["../../../src/astro/website-page-runtime.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAGzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2DAA2D,CAAC;AACrG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAI5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,gFAAgF;IAChF,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,yEAAyE;IACzE,WAAW,EAAE,kBAAkB,CAAC;IAChC,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,MAAM,EAAE,iBAAiB,CAAC;IAC1B;;;;;;;;OAQG;IACH,aAAa,EAAE,iBAAiB,CAAC;IACjC,qEAAqE;IACrE,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,6BAA6B,GAClC,kBAAkB,CAqCpB;AA+BD,+DAA+D"}
@@ -1 +1 @@
1
- {"version":3,"file":"website-site-context.d.ts","sourceRoot":"","sources":["../../../../src/astro/website-site-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAC;AACjG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IAEvC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,2BAA2B,CAAC;IACpD;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;CACrD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,kBAAkB,GACxB,kBAAkB,CAMpB;AACD,6DAA6D"}
1
+ {"version":3,"file":"website-site-context.d.ts","sourceRoot":"","sources":["../../../src/astro/website-site-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAC;AACjG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IAEvC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,2BAA2B,CAAC;IACpD;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;CACrD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,kBAAkB,GACxB,kBAAkB,CAMpB;AACD,6DAA6D"}
@@ -1 +1 @@
1
- {"version":3,"file":"astro-island.d.ts","sourceRoot":"","sources":["../../../src/astro-island.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAOH,cAAc,wBAAwB,CAAC;AACvC;;;;;;;;;;;;;;GAcG"}
1
+ {"version":3,"file":"astro-island.d.ts","sourceRoot":"","sources":["../../src/astro-island.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAOH,cAAc,wBAAwB,CAAC;AACvC;;;;;;;;;;;;;;GAcG"}
@@ -1 +1 @@
1
- {"version":3,"file":"astro.d.ts","sourceRoot":"","sources":["../../../src/astro.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAEH,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,2BAA2B,CAAC;AAC1C;;;;;;;;;;;GAWG;AACH,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD;;;;;;;;GAQG;AACH,cAAc,iCAAiC,CAAC;AAChD;;;;;;;;GAQG;AACH,cAAc,yBAAyB,CAAC;AACxC;;;;;;;;;;;;;;;;;;GAkBG;AACH,cAAc,0BAA0B,CAAC;AACzC;;;;;;;;;;GAUG;AACH,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC;;;;;;;;GAQG;AACH,cAAc,kEAAkE,CAAC"}
1
+ {"version":3,"file":"astro.d.ts","sourceRoot":"","sources":["../../src/astro.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAEH,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,2BAA2B,CAAC;AAC1C;;;;;;;;;;;GAWG;AACH,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD;;;;;;;;GAQG;AACH,cAAc,iCAAiC,CAAC;AAChD;;;;;;;;GAQG;AACH,cAAc,yBAAyB,CAAC;AACxC;;;;;;;;;;;;;;;;;;GAkBG;AACH,cAAc,0BAA0B,CAAC;AACzC;;;;;;;;;;GAUG;AACH,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC;;;;;;;;GAQG;AACH,cAAc,kEAAkE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"companion-exports.d.ts","sourceRoot":"","sources":["../../../src/companion-exports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AACnE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0DAA0D,CAAC;AACzE,cAAc,wDAAwD,CAAC;AACvE,cAAc,qDAAqD,CAAC;AACpE,cAAc,2CAA2C,CAAC"}
1
+ {"version":3,"file":"companion-exports.d.ts","sourceRoot":"","sources":["../../src/companion-exports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AACnE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0DAA0D,CAAC;AACzE,cAAc,wDAAwD,CAAC;AACvE,cAAc,qDAAqD,CAAC;AACpE,cAAc,2CAA2C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"WebsiteInternalButton.d.ts","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteInternalButton.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOlE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,iBAAiB,CAAC;AAmBzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,OAAO,EACP,IAAI,EACJ,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,EACT,QAAQ,GACT,EAAE,0BAA0B,GAAG,SAAS,CA+CxC;yBAxDe,qBAAqB;;;AA0DrC,qEAAqE"}
1
+ {"version":3,"file":"WebsiteInternalButton.d.ts","sourceRoot":"","sources":["../../../../src/components/low-level/WebsiteInternalButton.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOlE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,iBAAiB,CAAC;AAmBzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,OAAO,EACP,IAAI,EACJ,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,EACT,QAAQ,GACT,EAAE,0BAA0B,GAAG,SAAS,CA+CxC;yBAxDe,qBAAqB;;;AA0DrC,qEAAqE"}
@@ -1 +1 @@
1
- {"version":3,"file":"WebsiteInternalLink.d.ts","sourceRoot":"","sources":["../../../../../src/components/low-level/WebsiteInternalLink.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAqCD,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,EACT,QAAQ,GACT,EAAE,wBAAwB,GAAG,SAAS,CA8CtC;yBArDe,mBAAmB;;;AAuDnC,mEAAmE"}
1
+ {"version":3,"file":"WebsiteInternalLink.d.ts","sourceRoot":"","sources":["../../../../src/components/low-level/WebsiteInternalLink.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAqCD,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,EACT,QAAQ,GACT,EAAE,wBAAwB,GAAG,SAAS,CA8CtC;yBArDe,mBAAmB;;;AAuDnC,mEAAmE"}
@@ -1 +1 @@
1
- {"version":3,"file":"define-website-config.d.ts","sourceRoot":"","sources":["../../../../src/config/define-website-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,gCAAgC,EACtC,MAAM,gCAAgC,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,gCAAgC,GACvC,2BAA2B,CAI7B"}
1
+ {"version":3,"file":"define-website-config.d.ts","sourceRoot":"","sources":["../../../src/config/define-website-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,gCAAgC,EACtC,MAAM,gCAAgC,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,gCAAgC,GACvC,2BAA2B,CAI7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"load-website-config.d.ts","sourceRoot":"","sources":["../../../../src/config/load-website-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,oCAAoC,4BAA4B,CAAC;AAkB9E;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,kBAAkB,EAAE,MAAM,EAC1B,MAAM,EAAE,2BAA2B,GAClC,IAAI,CAEN;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,2BAA2B,CAAC,CA4DtC"}
1
+ {"version":3,"file":"load-website-config.d.ts","sourceRoot":"","sources":["../../../src/config/load-website-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,oCAAoC,4BAA4B,CAAC;AAkB9E;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,kBAAkB,EAAE,MAAM,EAC1B,MAAM,EAAE,2BAA2B,GAClC,IAAI,CAEN;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,2BAA2B,CAAC,CA4DtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"wildo-website-config.schemas.d.ts","sourceRoot":"","sources":["../../../../src/config/wildo-website-config.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsHG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,oDAAoD,CAAC;AAEvF;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB;;;kBASpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,iCAAiC;IAE1C;;;;;;;;;;OAUG;;IASH;;;;;;;;;;;;;;OAcG;;IAGH;;;;;;;;;;;;;;;;;;;;;;OAsBG;;IAWH;;;;;OAKG;;;;;;;;IAGH;;;;;;;;;OASG;;IAGH;;;;;;;;;OASG;;;;;kBAqDH,CAAC;AACL,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAC5F,MAAM,MAAM,gCAAgC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AACjG,wDAAwD"}
1
+ {"version":3,"file":"wildo-website-config.schemas.d.ts","sourceRoot":"","sources":["../../../src/config/wildo-website-config.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsHG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,oDAAoD,CAAC;AAEvF;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB;;;kBASpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,iCAAiC;IAE1C;;;;;;;;;;OAUG;;IASH;;;;;;;;;;;;;;OAcG;;IAGH;;;;;;;;;;;;;;;;;;;;;;OAsBG;;IAWH;;;;;OAKG;;;;;;;;IAGH;;;;;;;;;OASG;;IAGH;;;;;;;;;OASG;;;;;kBAqDH,CAAC;AACL,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAC5F,MAAM,MAAM,gCAAgC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AACjG,wDAAwD"}