@sonordev/site-kit 7.1.2 → 7.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +60 -0
  3. package/README.md +9 -8
  4. package/agent-manifest.json +17 -7
  5. package/dist/{AnalyticsProvider-ZB33W6MC.js → AnalyticsProvider-DJQA66AG.js} +4 -4
  6. package/dist/{ArticleViewTracker-GMHYLLLZ.js → ArticleViewTracker-GFOAXFV7.js} +3 -3
  7. package/dist/{BlocksPopup-EA6LYL25.js → BlocksPopup-AHDU34TL.js} +5 -5
  8. package/dist/ChatWidget-FHBAHFZX.js +17 -0
  9. package/dist/{FileField-QKA3JB2Q.js → FileField-J5W5MIAZ.js} +3 -3
  10. package/dist/{FormSpotlight-AQTIA5TP.js → FormSpotlight-PE5YZBFZ.js} +20 -6
  11. package/dist/{FormStage-FDTLTP3B.js → FormStage-OOPQC27J.js} +27 -7
  12. package/dist/ManagedForm-JRZAJ7SZ.js +16 -0
  13. package/dist/{ManagedNewsletterForm-J6QSAGGP.js → ManagedNewsletterForm-TC5542ZG.js} +7 -5
  14. package/dist/{SignalCore-JZNXOLNT.js → SignalCore-2YP5FCAS.js} +3 -3
  15. package/dist/SiteChat-EGEZJJVV.js +5 -0
  16. package/dist/{SiteDesignReporter-W4EJUSTE.js → SiteDesignReporter-YEEWJKWN.js} +5 -5
  17. package/dist/SitePopups-LQBIXIFV.js +10 -0
  18. package/dist/SitemapSync-LSZ2EYOF.js +8 -0
  19. package/dist/_client/booking-widget.js +5 -5
  20. package/dist/affiliates/index.js +3 -3
  21. package/dist/analytics/index.js +4 -4
  22. package/dist/analytics/send-gate.d.ts +1 -1
  23. package/dist/articles/index.js +2 -2
  24. package/dist/articles/server-ui.js +3 -2
  25. package/dist/articles/server.js +2 -1
  26. package/dist/{engage → chat}/ChatWidget.d.ts +7 -6
  27. package/dist/{engage → chat}/EchoUiActions.d.ts +1 -1
  28. package/dist/chat/SiteChat.d.ts +25 -0
  29. package/dist/{engage → chat}/brand-color.d.ts +1 -1
  30. package/dist/{engage → chat}/chat-messages.d.ts +1 -1
  31. package/dist/{engage → chat}/echo-config.d.ts +1 -1
  32. package/dist/chat/index.d.ts +10 -6
  33. package/dist/chat/index.js +14 -8
  34. package/dist/{engage → chat}/launcher-placement.d.ts +1 -7
  35. package/dist/{engage → chat}/socket-loader.d.ts +2 -2
  36. package/dist/chat/types.d.ts +136 -0
  37. package/dist/chunk-27FISYK4.js +4 -0
  38. package/dist/{chunk-HF57LG73.js → chunk-2AD3CDRR.js} +43 -29
  39. package/dist/{chunk-M3YEPKP7.js → chunk-2ECWEUHP.js} +1 -1
  40. package/dist/{chunk-LUXVWITO.js → chunk-4NTBQNHA.js} +247 -78
  41. package/dist/{chunk-AH5Q262S.js → chunk-56KNHB4U.js} +1 -1
  42. package/dist/{chunk-GLHQ3LRO.js → chunk-6U3VLV2C.js} +1 -1
  43. package/dist/{chunk-3SDOQUUF.js → chunk-BEBR4OJD.js} +2 -2
  44. package/dist/{chunk-JSZN6LDZ.js → chunk-BF7TZYC3.js} +38 -31
  45. package/dist/{chunk-AQSNPZY4.js → chunk-C2FZBUSS.js} +80 -1
  46. package/dist/{chunk-PHYMNUJU.js → chunk-CYUFBKJQ.js} +1 -1
  47. package/dist/{chunk-6WIQCXOO.js → chunk-DNPNYWVL.js} +1 -1
  48. package/dist/{chunk-V6FDQLR7.js → chunk-EPT6FJUY.js} +53 -21
  49. package/dist/chunk-HODO5BX5.js +28 -0
  50. package/dist/chunk-HW7B43E5.js +14 -0
  51. package/dist/{chunk-PGMVL4AB.js → chunk-I2YX3HVD.js} +2 -2
  52. package/dist/{chunk-JTU2GOM4.js → chunk-L7U23XI2.js} +18 -6
  53. package/dist/{chunk-YEMPUQVU.js → chunk-MKMD2HJW.js} +2 -2
  54. package/dist/{chunk-Q4W23JYM.js → chunk-MRQ2U4LZ.js} +1 -1
  55. package/dist/chunk-MVR4FY5R.js +187 -0
  56. package/dist/{chunk-VGH4MDTU.js → chunk-NI2XNEMR.js} +1 -1
  57. package/dist/{chunk-4Y5FWDPM.js → chunk-NZ4RXN3G.js} +55 -7
  58. package/dist/{chunk-RHNWA34F.js → chunk-O5RGXTWU.js} +41 -7
  59. package/dist/{chunk-TXBAOEKG.js → chunk-PKGN32AU.js} +5 -4
  60. package/dist/chunk-Q6E4OPGG.js +40 -0
  61. package/dist/chunk-RDPW4D33.js +45 -0
  62. package/dist/{chunk-UXOGCKL6.js → chunk-T4DLETKR.js} +1 -1
  63. package/dist/{chunk-NK4CSJNP.js → chunk-UPRSH6Q4.js} +2 -2
  64. package/dist/{chunk-ERXXITG4.js → chunk-VF4F5WXZ.js} +1 -1
  65. package/dist/chunk-VWWITFWM.js +300 -0
  66. package/dist/{chunk-WWSHFRDL.js → chunk-WDQB4OXY.js} +7 -3
  67. package/dist/{chunk-VDF5DFWT.js → chunk-WGG6GTKW.js} +1 -1
  68. package/dist/{chunk-CSTQDNGK.js → chunk-WGIDC6QP.js} +43 -24
  69. package/dist/{chunk-V3PUVBME.js → chunk-XLSQTTUE.js} +2 -4
  70. package/dist/{chunk-JBE46QJZ.js → chunk-Y6LP36UW.js} +1 -1
  71. package/dist/chunk-YJLS6JBI.js +370 -0
  72. package/dist/{chunk-QEDHRBAT.js → chunk-Z65DHMTW.js} +26 -9
  73. package/dist/{chunk-ILU5I6RW.js → chunk-ZHS2XFLV.js} +1 -1
  74. package/dist/{chunk-D5EC5KVO.js → chunk-ZKHI4E2B.js} +2 -2
  75. package/dist/{chunk-CIG5UL2S.js → chunk-ZTLMPUO6.js} +3 -2
  76. package/dist/client/index.js +3 -3
  77. package/dist/commerce/index.js +4 -4
  78. package/dist/contracts/color.d.ts +1 -1
  79. package/dist/contracts/entries.d.ts +1 -1
  80. package/dist/contracts/error-page.d.ts +183 -0
  81. package/dist/contracts/llms.d.ts +1 -0
  82. package/dist/contracts/proposal-sitemap.d.ts +130 -0
  83. package/dist/contracts/schema-placeholders.d.ts +87 -0
  84. package/dist/engage/EngageWidget.d.ts +13 -12
  85. package/dist/engage/index.d.ts +10 -9
  86. package/dist/engage/index.js +31 -35
  87. package/dist/engage/types.d.ts +19 -244
  88. package/dist/fleet/FleetHeartbeat.d.ts +1 -1
  89. package/dist/fleet/index.js +4 -4
  90. package/dist/forms/FormEnhancer.d.ts +25 -12
  91. package/dist/forms/ServerForm.d.ts +11 -10
  92. package/dist/forms/StaticForm.d.ts +3 -1
  93. package/dist/forms/field-autocomplete.d.ts +28 -0
  94. package/dist/forms/form-dom-values.d.ts +42 -0
  95. package/dist/forms/index.js +11 -9
  96. package/dist/forms/server.js +6 -4
  97. package/dist/forms/static.js +3 -2
  98. package/dist/forms/submitForm.d.ts +8 -1
  99. package/dist/forms/types.d.ts +41 -2
  100. package/dist/forms/useForm.d.ts +21 -4
  101. package/dist/forms/webmcp.d.ts +38 -0
  102. package/dist/images/index.js +4 -4
  103. package/dist/index.d.ts +4 -1
  104. package/dist/index.js +1 -1
  105. package/dist/layout/SiteKitClientProviders.d.ts +3 -3
  106. package/dist/layout/SiteKitLayout.d.ts +4 -4
  107. package/dist/layout/client.d.ts +3 -3
  108. package/dist/layout/client.js +7 -7
  109. package/dist/layout/index.js +8 -8
  110. package/dist/layout/types.d.ts +5 -4
  111. package/dist/llms/agent-access.d.ts +4 -0
  112. package/dist/llms/contract.js +1 -1
  113. package/dist/llms/index.js +6 -6
  114. package/dist/maps/index.js +3 -3
  115. package/dist/mcp/WebMcpTools.d.ts +5 -4
  116. package/dist/mcp/client.js +14 -7
  117. package/dist/mcp/discovery.d.ts +48 -0
  118. package/dist/mcp/handlers.d.ts +13 -7
  119. package/dist/mcp/index.d.ts +5 -3
  120. package/dist/mcp/index.js +62 -30
  121. package/dist/mcp/serverCard.d.ts +6 -7
  122. package/dist/mcp/sonor.js +14 -11
  123. package/dist/revalidate/index.js +2 -2
  124. package/dist/seo/client.js +4 -4
  125. package/dist/seo/index.js +15 -8
  126. package/dist/seo/llms/contract.js +1 -1
  127. package/dist/seo/llms.js +6 -6
  128. package/dist/seo/register-sitemap-cli.js +1 -1
  129. package/dist/seo/sitemap.js +4 -4
  130. package/dist/server/index.js +2 -2
  131. package/dist/shared/dialog.d.ts +27 -0
  132. package/dist/shared/identity.d.ts +1 -1
  133. package/dist/shared/layers.d.ts +7 -0
  134. package/dist/shared/mid-form.d.ts +53 -0
  135. package/dist/shared/reporting-gate.d.ts +1 -1
  136. package/dist/shared/version.d.ts +1 -1
  137. package/dist/shared/visual-viewport-gap.d.ts +1 -1
  138. package/dist/signal/index.js +2 -2
  139. package/dist/signal/types.d.ts +1 -1
  140. package/dist/sitemap/index.js +4 -4
  141. package/dist/{socket-loader-R24ZSRSQ.js → socket-loader-CGIPEG74.js} +1 -1
  142. package/dist/sync/index.js +5 -5
  143. package/dist/types.d.ts +3 -1
  144. package/dist/{web-vitals.attribution-GD6LGLVF.js → web-vitals.attribution-N2PCCF4Q.js} +1 -1
  145. package/dist/website/BlocksPopup.d.ts +1 -1
  146. package/dist/website/PopupBlocks.d.ts +5 -2
  147. package/dist/website/SitePopups.d.ts +25 -0
  148. package/dist/website/images.js +4 -4
  149. package/dist/website/index.js +6 -6
  150. package/dist/website/popup-rules.d.ts +46 -0
  151. package/dist/website/popup-types.d.ts +113 -0
  152. package/dist/website/popups.d.ts +2 -6
  153. package/dist/website/popups.js +6 -14
  154. package/dist/{writeLLMsTxt-G3JBNBC5.js → writeLLMsTxt-2NQVDGYI.js} +3 -3
  155. package/docs/MIGRATING-TO-7.md +41 -9
  156. package/docs.json +2 -1
  157. package/package.json +2 -2
  158. package/src/analytics/README.md +2 -2
  159. package/src/articles/README.md +4 -1
  160. package/src/{engage → chat}/README.md +63 -62
  161. package/src/forms/README.md +49 -3
  162. package/src/layout/README.md +8 -5
  163. package/src/llms/README.md +69 -0
  164. package/src/mcp/README.md +50 -16
  165. package/src/seo/README.md +3 -1
  166. package/src/sync/README.md +10 -0
  167. package/src/website/README.md +133 -0
  168. package/dist/ChatWidget-UCDWMWCW.js +0 -15
  169. package/dist/EngageWidget-7ZYSK4GE.js +0 -11
  170. package/dist/ManagedForm-H7BVAH2W.js +0 -14
  171. package/dist/SitemapSync-XBANGKHZ.js +0 -8
  172. package/dist/chunk-NDF4A5JM.js +0 -37
  173. package/dist/chunk-VLARKWZU.js +0 -100
  174. package/dist/chunk-YCJT4JJG.js +0 -837
  175. package/dist/engage/DesignRenderer.d.ts +0 -57
  176. package/dist/engage/element-rules.d.ts +0 -38
package/AGENTS.md CHANGED
@@ -81,7 +81,7 @@ whole tree client-side and breaks RSC/SSR). `codemod` migrates it for you.
81
81
 
82
82
  **Analytics is already a deferred, childless sibling. Don't wrap `{children}`,
83
83
  and don't hand-roll it.** Since 3.0.2, `SiteKitLayout` renders `{children}`
84
- first and mounts analytics, engage and the fleet heartbeat after it, deferred
84
+ first and mounts analytics, chat, popups and the fleet heartbeat after it, deferred
85
85
  to window load + idle (or the first interaction). 4.0.0 removed the last
86
86
  wrappers. So the plain layout above is the whole pattern: configure analytics
87
87
  with `analytics={{ ... }}`, and track custom events with the standalone
package/CHANGELOG.md CHANGED
@@ -1,5 +1,65 @@
1
1
  # @sonordev/site-kit Changelog
2
2
 
3
+ ## 7.3.0
4
+
5
+ AI assistants can discover a site's existing MCP tools through more of the surfaces they read.
6
+
7
+ - **WebMCP registers promptly.** Supported browsers discover tools when the component mounts; ordinary browsers make no discovery request. Optional `defer` remains available, and ordinary rerenders no longer replace registrations.
8
+ - **Experimental AI catalog.** `createMcpAiCatalogHandler` and `buildMcpAiCatalog` advertise the existing server card from `/.well-known/ai-catalog.json`. Cards can serve the draft media type at `/api/mcp/server-card`; legacy card URLs retain JSON. Discovery responses support public caching, CORS and ETags without reading the request during static rendering.
9
+ - **Discovery in llms.txt.** The shared `mcp` configuration accepts an optional catalog URL and `position: 'after-intro'`. Build-time files and route handlers use the same section, including when the handler serves an older static file. Existing site-authored MCP sections stay intact.
10
+ - **Companion CLI:** sonor-setup 7.2.0 generates the catalog and canonical card routes while preserving custom-server implementations and compatibility aliases.
11
+
12
+ ## 7.2.0
13
+
14
+ Forms, popups and booking now work the way AI agent browsers, autofill and screen readers expect, Sonor's schema can't put a template's placeholders on a live page, and the retired Engage module is gone from the kit. No site changes needed: update the package and rebuild.
15
+
16
+ ### Engage is gone
17
+
18
+ Engage was retired in Sonor; its chat lives in Messages and its popups in Website. The kit now matches.
19
+
20
+ - **Chat and popups load on their own.** Website chat is `@sonordev/site-kit/chat` and popups are `@sonordev/site-kit/website/popups`. `SiteKitLayout` mounts `SiteChat` and `SitePopups` as separate deferred siblings, so a site with popups off never downloads the chat, and the other way round. The popups entry is 16% smaller.
21
+ - **Popups render from blocks only.** A popup made in Engage Studio (one without blocks) isn't drawn: make it again in Website → Popups & Banners. `DesignRenderer` and its types are removed.
22
+ - **New:** `SiteChat` in `./chat`, the standalone chat mount (idle-deferred, gated like analytics), and the popup types under their own names in `./website/popups` (`SitePopup`, `SitePopupConfig`, `SitePopupTargeting`, `SitePopupTrigger`, `SitePopupType`).
23
+ - **`@sonordev/site-kit/engage` still builds through 7.x.** `ChatWidget` and the chat types re-export from it, the popup types keep their old names (`EngageElement` is `SitePopup`), and `EngageWidget` draws `SiteChat` and `SitePopups`. sonor-setup's codemod moves the imports. It's removed in 8.0.
24
+
25
+ See [Website chat](src/chat/README.md) and [Popups and banners](src/website/README.md).
26
+
27
+ ### Agent-ready forms
28
+
29
+ - **Autocomplete tokens.** Name, email, phone, company, address and website fields carry the matching `autocomplete` token (`given-name`, `email`, `tel`, `organization`, `postal-code`, and so on), read from the field's CRM destination, then its type, slug or a short label. A field it can't match confidently gets none, since a wrong token is worse than no token.
30
+ - **Accessible wiring.** Every control is tied to its label, help text and error (`aria-describedby`, `aria-invalid`, errors announced with `role="alert"`). Radio and checkbox groups are named by their question, rating stars say which one is chosen, and the required asterisk is hidden from assistive tech, since `required` already says it.
31
+ - **WebMCP.** The interactive form declares itself as a tool (`toolname`, `tooldescription`, and `toolparamdescription` on fields with help text), so a browser that supports WebMCP can offer it to an agent. Forms never set `toolautosubmit`: an agent fills the form and the person still sends it. When an agent does send it, the browser gets the outcome back, and the submission is marked "Sent by an AI assistant" in Sonor.
32
+ - **Nothing typed is lost.** The server-rendered form stays on the page until the interactive one has loaded. What was typed or autofilled carries across, focus stays in its field, and a Send pressed early is held and sent once the form is ready. The server form's Send button is disabled until it can catch a submit, and a visitor without JavaScript is told why the form won't send.
33
+ - **`submit()` returns the outcome.** From `useForm` and the form render props: `{ status: 'sent' | 'invalid' | 'failed' | 'busy' | 'next_step', ... }`. `useForm` also returns `handleSubmit` and `toolAttributes` for custom markup: `<form {...toolAttributes} onSubmit={handleSubmit}>`.
34
+ - `ServerForm`'s `enhance` prop is deprecated and ignored. Every server form upgrades to the interactive one.
35
+
36
+ See [Forms](src/forms/README.md).
37
+
38
+ ### Popups wait for forms, and every popup is a named dialog
39
+
40
+ - A popup or toast that opens on its own (immediately, after a delay, on scroll or on exit intent) waits while the visitor is in the middle of a form: focus in a field, a filled-in field not yet sent, or a form that's sending. It opens a moment after they leave the form, or once it's sent. Banners still show at once.
41
+ - A popup is a modal dialog named by its heading: it takes focus, keeps Tab inside, closes on Escape and returns focus where it was. A toast is a named non-modal dialog and a bar is a named region. Close buttons are named "Close".
42
+
43
+ See [Popups and banners](src/website/README.md).
44
+
45
+ ### BookingWidget
46
+
47
+ - Day buttons are named with the full date, year included ("Wednesday, October 7, 2026"), and time buttons with the time and date in the booking's time zone. The picked day and time are pressed (`aria-pressed`). Confirm is named with what it confirms ("Confirm 10:30 AM, Wednesday, October 7, 2026"). Every name starts with what its button shows, so voice control still works. What the widget sends is unchanged.
48
+
49
+ See [Sync](src/sync/README.md).
50
+
51
+ ### SEO and AI visibility
52
+
53
+ - **Template placeholders never reach the page.** `ManagedSchema`, `LLMSchema` and `generateAllArticleSchemas` drop placeholder nodes from Sonor-supplied schema: a URL on a reserved example domain, a name like "Example" or "Your Business Name", a placeholder phone, a slot like `[Resident Name]` or `{plan.name}`, or an object that's only a note. Real siblings and parents stay, and an article whose stored schema is nothing but placeholders gets its generated schema instead. Your own `additionalSchemas` are never touched. The rule is `@sonordev/contracts/schema-placeholders`.
54
+ - **llms.txt summaries end at a word.** A long page summary ends at a sentence or a whole word, never mid-word.
55
+
56
+ See [SEO](src/seo/README.md) and [Articles](src/articles/README.md).
57
+
58
+ ### Also
59
+
60
+ - Built and tested against Next.js 16.3.8, the September 30 security release. Update `next` on each site; the peer range is unchanged.
61
+ - The 7.0 migration guide covers sonor-setup 7.1.2's proxy fix: on a `src/app` site the proxy belongs in `src/`.
62
+
3
63
  ## 7.1.2
4
64
 
5
65
  Docs and comments only; no code changes.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @sonordev/site-kit
2
2
 
3
- All-in-one integration kit for [Sonor](https://sonor.io)-powered Next.js sites. One package, one env var, every module: SEO, Analytics, Forms, Articles, Commerce, Engage, GEO/AEO, Booking, Reputation, A/B Testing, and more — all managed from the Sonor dashboard at [app.sonor.io](https://app.sonor.io).
3
+ All-in-one integration kit for [Sonor](https://sonor.io)-powered Next.js sites. One package, one env var, every module: SEO, Analytics, Forms, Articles, Commerce, Website chat, Popups, GEO/AEO, Booking, Reputation, A/B Testing, and more — all managed from the Sonor dashboard at [app.sonor.io](https://app.sonor.io).
4
4
 
5
5
  ## Install
6
6
 
@@ -53,7 +53,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
53
53
  }
54
54
  ```
55
55
 
56
- `SiteKitLayout` is an RSC-compatible async Server Component that auto-composes: analytics tracking, Engage widgets, favicons, and managed scripts. No client-side provider wrapping needed: client modules mount as deferred siblings after `{children}`, so the page stays server-rendered. Props and module options: [src/layout/README.md](src/layout/README.md).
56
+ `SiteKitLayout` is an RSC-compatible async Server Component that auto-composes: analytics tracking, website chat, popups, favicons, and managed scripts. No client-side provider wrapping needed: client modules mount as deferred siblings after `{children}`, so the page stays server-rendered. Props and module options: [src/layout/README.md](src/layout/README.md).
57
57
 
58
58
  **Proxy (optional but recommended):**
59
59
 
@@ -112,8 +112,8 @@ Every module has its own README in `src/<module>/README.md` with full API docs,
112
112
 
113
113
  | Module | Import | Purpose | Docs |
114
114
  |--------|--------|---------|------|
115
- | **Website chat** | `@sonordev/site-kit/chat` | The chat launcher and Echo (Sonor → Messages) | [README](src/engage/README.md) |
116
- | **Popups & Banners** | `@sonordev/site-kit/website/popups` | Popups, banners and toasts from Sonor → Website, drawn in the site's own design | [contract](src/website/contract.ts) |
115
+ | **Website chat** | `@sonordev/site-kit/chat` | The chat launcher and Echo (Sonor → Messages) | [README](src/chat/README.md) |
116
+ | **Popups & Banners** | `@sonordev/site-kit/website/popups` | Popups, banners and toasts from Sonor → Website, drawn in the site's own design | [README](src/website/README.md) |
117
117
  | **Forms** | `@sonordev/site-kit/forms` | Managed forms with CRM routing, multi-step, validation | [README](src/forms/README.md) |
118
118
  | **Signal** | `@sonordev/site-kit/signal` | A/B experiments, behavior tracking, real-time config | [README](src/signal/README.md) |
119
119
 
@@ -149,7 +149,7 @@ Three tiers as three subpaths — a site only installs and ships what it imports
149
149
  |--------|--------|---------|------|
150
150
  | **CTA bar** | `@sonordev/site-kit/website/cta-bar` | `<CtaBar>` + `<CtaBarAction>`: the floating glass mobile CTA bar. Hides over its form and while typing, compacts on scroll, lifts the Echo launcher, emits `cta_click`. Server component. | [README](src/cta-bar/README.md) |
151
151
 
152
- Echo's launcher and chat window use the same glass recipe; see [Engage](src/engage/README.md#liquid-glass-610).
152
+ Echo's launcher and chat window use the same glass recipe; see [Website chat](src/chat/README.md#liquid-glass-610).
153
153
 
154
154
  ---
155
155
 
@@ -167,7 +167,8 @@ SiteKitLayout (RSC server component)
167
167
  │
168
168
  ├── Client-side (childless siblings after {children}, deferred to idle):
169
169
  │ ├── AnalyticsProvider (page views, scroll depth, Web Vitals)
170
- │ ├── EngageWidget (popups, nudges, chat)
170
+ │ ├── SitePopups (popups, banners, toasts)
171
+ │ ├── SiteChat (website chat: Echo)
171
172
  │ ├── SignalBridge (A/B experiments, opt-in, not deferred)
172
173
  │ ├── SitemapSync (browser sitemap fallback, opt-in)
173
174
  │ └── FleetHeartbeat (kit version + modules, once per session)
@@ -209,7 +210,7 @@ import { OfferingCard, ProductPage, EventCalendar } from '@sonordev/site-kit/com
209
210
  import { BookingWidget } from '@sonordev/site-kit/sync'
210
211
 
211
212
  // Website chat, and popups (SiteKitLayout mounts both; its `chat` and `popups` props turn them off)
212
- import { ChatWidget } from '@sonordev/site-kit/chat'
213
+ import { SiteChat, ChatWidget } from '@sonordev/site-kit/chat'
213
214
  import { SitePopups, PopupBlocks } from '@sonordev/site-kit/website/popups'
214
215
 
215
216
  // Signal (A/B)
@@ -322,7 +323,7 @@ import type { SiteKitLayoutProps } from '@sonordev/site-kit/layout'
322
323
  `@sonordev/site-kit` is the client bridge between Next.js marketing sites and the Sonor platform. All persistent data (forms, articles, SEO config, analytics) lives in Sonor — site-kit fetches, renders, and tracks.
323
324
 
324
325
  - **Server components** (SEO, Articles, Images): Import directly, RSC-compatible, no provider needed
325
- - **Client modules** (Analytics, Engage, Signal): Lazy-loaded via `SiteKitLayout`, tree-shaken
326
+ - **Client modules** (Analytics, chat, popups, Signal): Lazy-loaded via `SiteKitLayout`, tree-shaken
326
327
  - **Build-time** (Sitemap, llms.txt): Run during `next build`, sync to Sonor
327
328
  - **Middleware** (Redirects, Security, AI Discovery): Runs on every request edge
328
329
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@sonordev/site-kit",
4
- "version": "7.1.2",
4
+ "version": "7.3.0",
5
5
  "description": "Machine-readable manifest for coding agents integrating a site with Sonor. See AGENTS.md (shipped) and docs/SITE-KIT-AGENT-NATIVE.md.",
6
6
  "env": {
7
7
  "required": [
@@ -90,7 +90,7 @@
90
90
  "name": "mcp",
91
91
  "json": true,
92
92
  "interactive": false,
93
- "purpose": "Give agents the site's tools: writes the MCP server (site-kit's built-in Sonor tools), the endpoint with tool-call reporting, the server card, and on Netlify the rate-limited relay. Never overwrites without --force; --dry-run to preview."
93
+ "purpose": "Give agents the site's tools: writes the MCP server (site-kit's built-in Sonor tools), the endpoint with tool-call reporting, the canonical server card and compatibility aliases, the experimental AI catalog, and on Netlify the rate-limited relay. Never overwrites without --force; --dry-run to preview."
94
94
  },
95
95
  {
96
96
  "name": "next16",
@@ -139,7 +139,8 @@
139
139
  "name": "engage",
140
140
  "import": "@sonordev/site-kit/engage",
141
141
  "side": "client",
142
- "purpose": "Popups, nudges, banners, chat widget configured in Sonor.",
142
+ "purpose": "Deprecated alias, kept through 7.x: Engage was retired in Sonor. Re-exports ./chat (ChatWidget, chat types) and ./website/popups under the old names; EngageWidget draws SiteChat and SitePopups.",
143
+ "caution": "Import ./chat or ./website/popups instead, or let SiteKitLayout mount both (its chat and popups props). DesignRenderer (Engage Studio) is gone; popups render from blocks.",
143
144
  "stability": "deprecated",
144
145
  "movedTo": [
145
146
  "@sonordev/site-kit/chat",
@@ -293,12 +294,14 @@
293
294
  {
294
295
  "name": "mcp",
295
296
  "import": "@sonordev/site-kit/mcp",
296
- "side": "unknown"
297
+ "side": "server",
298
+ "purpose": "Remote MCP tools and static discovery: createMcpHandler, createMcpServerCardHandler, and createMcpAiCatalogHandler. The AI catalog is experimental; keep existing card aliases and derive all surfaces from one server definition."
297
299
  },
298
300
  {
299
301
  "name": "mcp/client",
300
302
  "import": "@sonordev/site-kit/mcp/client",
301
- "side": "unknown"
303
+ "side": "client",
304
+ "purpose": "WebMcpTools registers tools promptly in supported browsers using the same remote tools/list catalog. Unsupported browsers make no discovery request. Mount as a childless sibling; defer is optional."
302
305
  },
303
306
  {
304
307
  "name": "mcp/transport",
@@ -387,13 +390,13 @@
387
390
  "name": "chat",
388
391
  "import": "@sonordev/site-kit/chat",
389
392
  "side": "client",
390
- "purpose": "Website chat (Sonor → Messages): ChatWidget, the launcher and Echo. SiteKitLayout mounts it (its `chat` prop); import it to place it yourself."
393
+ "purpose": "Website chat (Sonor → Messages): SiteChat (idle-deferred launcher, gated like analytics), ChatWidget and Echo. SiteKitLayout mounts it (its `chat` prop); import it to place it yourself."
391
394
  },
392
395
  {
393
396
  "name": "website/popups",
394
397
  "import": "@sonordev/site-kit/website/popups",
395
398
  "side": "client",
396
- "purpose": "Website → Popups & Banners: SitePopups shows the popups published for this site, drawn in its own design; PopupBlocks renders one from its blocks. SiteKitLayout mounts it (its `popups` prop)."
399
+ "purpose": "Website → Popups & Banners: SitePopups shows the popups, banners and toasts published for the site (only those with blocks), waiting while a visitor is mid-form; PopupBlocks draws one. SiteKitLayout mounts it (its `popups` prop)."
397
400
  },
398
401
  {
399
402
  "name": "website/images",
@@ -732,6 +735,13 @@
732
735
  "fix": "Remove the runtime export, then `npx sonor-setup codemod --write` moves the file to proxy.ts.",
733
736
  "check": "middleware.netlify"
734
737
  },
738
+ {
739
+ "id": "proxy.misplaced",
740
+ "symptom": "The build passes, but the site sends no security headers and runs no Sonor-managed redirects.",
741
+ "cause": "The proxy file sits where Next never reads it. Next reads proxy.ts (and the deprecated middleware.ts) only from the directory that holds the app: the project root, or src/ when the app is src/app. A proxy.ts at the root of a src/app site is ignored without a warning. sonor-setup 7.1.1's codemod renamed middleware.ts in place, which left it at the root on src/app sites.",
742
+ "fix": "Run `npx sonor-setup codemod --write` (7.1.2 or later): it moves the proxy beside the app and fixes its relative imports. It never overwrites, so when a proxy exists in both places it reports both and you keep the right one by hand. Rebuild and re-run doctor.",
743
+ "check": "middleware.netlify"
744
+ },
735
745
  {
736
746
  "id": "sitemap.trailing-slash",
737
747
  "symptom": "Every sitemap URL except / 308-redirects to the same path with a trailing slash; the sitemap disagrees with the canonicals.",
@@ -1,11 +1,11 @@
1
- export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-YEMPUQVU.js';
1
+ export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-MKMD2HJW.js';
2
2
  import './chunk-LCDVPAMR.js';
3
3
  import './chunk-24QZEO3Q.js';
4
4
  import './chunk-L2V5PUFN.js';
5
5
  import './chunk-GJWI74ZZ.js';
6
6
  import './chunk-43OCZ3JA.js';
7
7
  import './chunk-EKBEOXTH.js';
8
- import './chunk-3SDOQUUF.js';
9
- import './chunk-VDF5DFWT.js';
10
- import './chunk-AH5Q262S.js';
8
+ import './chunk-BEBR4OJD.js';
9
+ import './chunk-WGG6GTKW.js';
10
+ import './chunk-56KNHB4U.js';
11
11
  import './chunk-PKBMQBKP.js';
@@ -3,9 +3,9 @@ import { useDeferredActivation } from './chunk-YC7ELZS3.js';
3
3
  import { withSiteBody } from './chunk-MJP63SSS.js';
4
4
  import './chunk-FESKKJAS.js';
5
5
  import './chunk-A4CC4ZG3.js';
6
- import { sonorFetch } from './chunk-3SDOQUUF.js';
7
- import './chunk-VDF5DFWT.js';
8
- import './chunk-AH5Q262S.js';
6
+ import { sonorFetch } from './chunk-BEBR4OJD.js';
7
+ import './chunk-WGG6GTKW.js';
8
+ import './chunk-56KNHB4U.js';
9
9
  import './chunk-PKBMQBKP.js';
10
10
  import { useEffect } from 'react';
11
11
 
@@ -1,13 +1,13 @@
1
1
  'use client';
2
- import { getSiteDesignTokens } from './chunk-PGMVL4AB.js';
3
- import { DEFAULT_POPUP_TOKENS, PopupBlocks } from './chunk-JSZN6LDZ.js';
2
+ import { getSiteDesignTokens } from './chunk-I2YX3HVD.js';
3
+ import { DEFAULT_POPUP_TOKENS, PopupBlocks } from './chunk-BF7TZYC3.js';
4
4
  import { normalizePopupBlocks, toHexColor, readableOn } from './chunk-IHG36STL.js';
5
5
  import './chunk-S22FSH7C.js';
6
6
  import './chunk-43OCZ3JA.js';
7
7
  import './chunk-EKBEOXTH.js';
8
- import './chunk-3SDOQUUF.js';
9
- import './chunk-VDF5DFWT.js';
10
- import './chunk-AH5Q262S.js';
8
+ import './chunk-BEBR4OJD.js';
9
+ import './chunk-WGG6GTKW.js';
10
+ import './chunk-56KNHB4U.js';
11
11
  import './chunk-PKBMQBKP.js';
12
12
  import { useState } from 'react';
13
13
  import { jsx } from 'react/jsx-runtime';
@@ -0,0 +1,17 @@
1
+ export { ChatWidget, EchoChat, isChatEnabled } from './chunk-O5RGXTWU.js';
2
+ import './chunk-6T6CQVNL.js';
3
+ import './chunk-JE4A5S4F.js';
4
+ import './chunk-27FISYK4.js';
5
+ import './chunk-EPT6FJUY.js';
6
+ import './chunk-Q6E4OPGG.js';
7
+ import './chunk-C2FZBUSS.js';
8
+ import './chunk-5SQK3D53.js';
9
+ import './chunk-HW7B43E5.js';
10
+ import './chunk-NJCTQH2P.js';
11
+ import './chunk-S22FSH7C.js';
12
+ import './chunk-L2V5PUFN.js';
13
+ import './chunk-GJWI74ZZ.js';
14
+ import './chunk-BEBR4OJD.js';
15
+ import './chunk-WGG6GTKW.js';
16
+ import './chunk-56KNHB4U.js';
17
+ import './chunk-PKBMQBKP.js';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
- import { sonorFetch } from './chunk-3SDOQUUF.js';
3
- import './chunk-VDF5DFWT.js';
4
- import './chunk-AH5Q262S.js';
2
+ import { sonorFetch } from './chunk-BEBR4OJD.js';
3
+ import './chunk-WGG6GTKW.js';
4
+ import './chunk-56KNHB4U.js';
5
5
  import './chunk-PKBMQBKP.js';
6
6
  import React from 'react';
7
7
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
@@ -1,8 +1,11 @@
1
1
  'use client';
2
2
  import { StageStyles, SummaryTick } from './chunk-J4FSB4OG.js';
3
- import { stageFirstName, useFieldControls, stageViews, stageEstimate, AUTO_ADVANCE_TYPES } from './chunk-D5EC5KVO.js';
4
- import { FormField } from './chunk-LUXVWITO.js';
5
- import { isEmptyValue, isDisplayOnly } from './chunk-AQSNPZY4.js';
3
+ import { stageFirstName, useFieldControls, stageViews, stageEstimate, AUTO_ADVANCE_TYPES } from './chunk-ZKHI4E2B.js';
4
+ import { FormField } from './chunk-4NTBQNHA.js';
5
+ import { readAgentSubmit, formToolAttributes } from './chunk-Q6E4OPGG.js';
6
+ import { isEmptyValue, unseenControlValues, isDisplayOnly } from './chunk-C2FZBUSS.js';
7
+ import './chunk-HW7B43E5.js';
8
+ import { DEFAULT_HONEYPOT_FIELD } from './chunk-NJCTQH2P.js';
6
9
  import './chunk-PKBMQBKP.js';
7
10
  import { useMemo, useCallback, useState, useRef, useEffect } from 'react';
8
11
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -527,11 +530,21 @@ function FormSpotlight({
527
530
  const handleSubmit = useCallback(
528
531
  (e) => {
529
532
  e.preventDefault();
530
- if (isSubmitting) return;
533
+ const agent = readAgentSubmit(e.nativeEvent);
534
+ if (isSubmitting) {
535
+ agent.respond(Promise.resolve({ status: "busy" }));
536
+ return;
537
+ }
531
538
  clearAutoTimer();
532
- void submit();
539
+ const domFills = unseenControlValues(
540
+ e.currentTarget,
541
+ config.fields,
542
+ config.honeypot_field || DEFAULT_HONEYPOT_FIELD,
543
+ values
544
+ );
545
+ agent.respond(submit({ agentInvoked: agent.invoked, domFills }));
533
546
  },
534
- [isSubmitting, submit, clearAutoTimer]
547
+ [isSubmitting, submit, clearAutoTimer, config, values]
535
548
  );
536
549
  useEffect(() => {
537
550
  const offender = questions.find((q) => errors[q.slug]);
@@ -560,6 +573,7 @@ function FormSpotlight({
560
573
  ref: formRef,
561
574
  className: `sk-form sk-spot ${live ? "sk-spot--live " : ""}${className || ""}`,
562
575
  "data-sk-part": "spotlight",
576
+ ...formToolAttributes(config),
563
577
  "data-sk-state": isSubmitting ? "submitting" : "idle",
564
578
  "data-sk-ready": ready && momentum.total > 0 ? "true" : void 0,
565
579
  onSubmit: handleSubmit,
@@ -1,8 +1,11 @@
1
1
  'use client';
2
2
  import { StageStyles, SummaryTick } from './chunk-J4FSB4OG.js';
3
- import { useFieldControls, stageViews, stageFirstName, stageEstimate, formatAnswer, AUTO_ADVANCE_TYPES } from './chunk-D5EC5KVO.js';
4
- import { FormField } from './chunk-LUXVWITO.js';
5
- import { isEmptyValue } from './chunk-AQSNPZY4.js';
3
+ import { useFieldControls, stageViews, stageFirstName, stageEstimate, formatAnswer, AUTO_ADVANCE_TYPES } from './chunk-ZKHI4E2B.js';
4
+ import { FormField } from './chunk-4NTBQNHA.js';
5
+ import { readAgentSubmit, formToolAttributes } from './chunk-Q6E4OPGG.js';
6
+ import { isEmptyValue, unseenControlValues } from './chunk-C2FZBUSS.js';
7
+ import './chunk-HW7B43E5.js';
8
+ import { DEFAULT_HONEYPOT_FIELD } from './chunk-NJCTQH2P.js';
6
9
  import './chunk-PKBMQBKP.js';
7
10
  import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
8
11
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -205,11 +208,27 @@ function FormStage({
205
208
  const handleSubmit = useCallback(
206
209
  (e) => {
207
210
  e.preventDefault();
208
- if (isSubmitting) return;
209
- if (activeIndex !== REST) advance();
210
- else void submit();
211
+ const agent = readAgentSubmit(e.nativeEvent);
212
+ if (isSubmitting) {
213
+ agent.respond(Promise.resolve({ status: "busy" }));
214
+ return;
215
+ }
216
+ if (activeIndex !== REST) {
217
+ advance();
218
+ agent.respond(
219
+ Promise.resolve({ status: "next_step", step: activeIndex + 2, totalSteps: views.length })
220
+ );
221
+ return;
222
+ }
223
+ const domFills = unseenControlValues(
224
+ e.currentTarget,
225
+ config.fields,
226
+ config.honeypot_field || DEFAULT_HONEYPOT_FIELD,
227
+ values
228
+ );
229
+ agent.respond(submit({ agentInvoked: agent.invoked, domFills }));
211
230
  },
212
- [activeIndex, isSubmitting, advance, submit]
231
+ [activeIndex, isSubmitting, advance, submit, config, values, views.length]
213
232
  );
214
233
  const handleFinaleSubmit = useCallback(() => {
215
234
  hasInteractedRef.current = true;
@@ -230,6 +249,7 @@ function FormStage({
230
249
  ref: formRef,
231
250
  className: `sk-form sk-stage ${className || ""}`,
232
251
  "data-sk-part": "stage",
252
+ ...formToolAttributes(config),
233
253
  "data-sk-state": isSubmitting ? "submitting" : "idle",
234
254
  "data-sk-ready": activeIndex === REST && ready && total > 0 ? "true" : void 0,
235
255
  onSubmit: handleSubmit,
@@ -0,0 +1,16 @@
1
+ export { ManagedForm } from './chunk-WGIDC6QP.js';
2
+ import './chunk-ZKHI4E2B.js';
3
+ import './chunk-DXO6SBMD.js';
4
+ import './chunk-4NTBQNHA.js';
5
+ import './chunk-EPT6FJUY.js';
6
+ import './chunk-Q6E4OPGG.js';
7
+ import './chunk-C2FZBUSS.js';
8
+ import './chunk-5SQK3D53.js';
9
+ import './chunk-HW7B43E5.js';
10
+ import './chunk-NJCTQH2P.js';
11
+ import './chunk-L2V5PUFN.js';
12
+ import './chunk-GJWI74ZZ.js';
13
+ import './chunk-BEBR4OJD.js';
14
+ import './chunk-WGG6GTKW.js';
15
+ import './chunk-56KNHB4U.js';
16
+ import './chunk-PKBMQBKP.js';
@@ -1,14 +1,16 @@
1
1
  import { NewsletterShell } from './chunk-SC4MZGWZ.js';
2
2
  import './chunk-GYF2ULVO.js';
3
- import { useForm } from './chunk-V6FDQLR7.js';
4
- import './chunk-AQSNPZY4.js';
3
+ import { useForm } from './chunk-EPT6FJUY.js';
4
+ import './chunk-Q6E4OPGG.js';
5
+ import './chunk-C2FZBUSS.js';
5
6
  import './chunk-5SQK3D53.js';
7
+ import './chunk-HW7B43E5.js';
6
8
  import './chunk-NJCTQH2P.js';
7
9
  import './chunk-L2V5PUFN.js';
8
10
  import './chunk-GJWI74ZZ.js';
9
- import './chunk-3SDOQUUF.js';
10
- import './chunk-VDF5DFWT.js';
11
- import './chunk-AH5Q262S.js';
11
+ import './chunk-BEBR4OJD.js';
12
+ import './chunk-WGG6GTKW.js';
13
+ import './chunk-56KNHB4U.js';
12
14
  import './chunk-PKBMQBKP.js';
13
15
  import { jsx } from 'react/jsx-runtime';
14
16
 
@@ -2,9 +2,9 @@
2
2
  import { getOrCreateVisitorId, getOrCreateSessionId } from './chunk-24QZEO3Q.js';
3
3
  import { onPageLeave } from './chunk-L2V5PUFN.js';
4
4
  import './chunk-GJWI74ZZ.js';
5
- import { sonorFetch } from './chunk-3SDOQUUF.js';
6
- import { getFreshCredential, isSiteToken } from './chunk-VDF5DFWT.js';
7
- import './chunk-AH5Q262S.js';
5
+ import { sonorFetch } from './chunk-BEBR4OJD.js';
6
+ import { getFreshCredential, isSiteToken } from './chunk-WGG6GTKW.js';
7
+ import './chunk-56KNHB4U.js';
8
8
  import './chunk-PKBMQBKP.js';
9
9
  import { useState, useRef, useEffect, useCallback } from 'react';
10
10
 
@@ -0,0 +1,5 @@
1
+ export { SiteChat } from './chunk-RDPW4D33.js';
2
+ import './chunk-27FISYK4.js';
3
+ import './chunk-43OCZ3JA.js';
4
+ import './chunk-EKBEOXTH.js';
5
+ import './chunk-PKBMQBKP.js';
@@ -1,11 +1,11 @@
1
- export { SiteDesignReporter } from './chunk-Q4W23JYM.js';
2
- import './chunk-PGMVL4AB.js';
1
+ export { SiteDesignReporter } from './chunk-MRQ2U4LZ.js';
2
+ import './chunk-I2YX3HVD.js';
3
3
  import './chunk-IHG36STL.js';
4
4
  import './chunk-YC7ELZS3.js';
5
5
  import './chunk-S22FSH7C.js';
6
6
  import './chunk-43OCZ3JA.js';
7
7
  import './chunk-EKBEOXTH.js';
8
- import './chunk-3SDOQUUF.js';
9
- import './chunk-VDF5DFWT.js';
10
- import './chunk-AH5Q262S.js';
8
+ import './chunk-BEBR4OJD.js';
9
+ import './chunk-WGG6GTKW.js';
10
+ import './chunk-56KNHB4U.js';
11
11
  import './chunk-PKBMQBKP.js';
@@ -0,0 +1,10 @@
1
+ export { SitePopups } from './chunk-YJLS6JBI.js';
2
+ import './chunk-27FISYK4.js';
3
+ import './chunk-24QZEO3Q.js';
4
+ import './chunk-GJWI74ZZ.js';
5
+ import './chunk-43OCZ3JA.js';
6
+ import './chunk-EKBEOXTH.js';
7
+ import './chunk-BEBR4OJD.js';
8
+ import './chunk-WGG6GTKW.js';
9
+ import './chunk-56KNHB4U.js';
10
+ import './chunk-PKBMQBKP.js';
@@ -0,0 +1,8 @@
1
+ export { SitemapSync } from './chunk-T4DLETKR.js';
2
+ import './chunk-YVKRYQRG.js';
3
+ import './chunk-43OCZ3JA.js';
4
+ import './chunk-EKBEOXTH.js';
5
+ import './chunk-BEBR4OJD.js';
6
+ import './chunk-WGG6GTKW.js';
7
+ import './chunk-56KNHB4U.js';
8
+ import './chunk-PKBMQBKP.js';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
- export { BookingWidget, BookingWidget_default as default } from '../chunk-JTU2GOM4.js';
3
- import '../chunk-M3YEPKP7.js';
4
- import '../chunk-3SDOQUUF.js';
5
- import '../chunk-VDF5DFWT.js';
6
- import '../chunk-AH5Q262S.js';
2
+ export { BookingWidget, BookingWidget_default as default } from '../chunk-L7U23XI2.js';
3
+ import '../chunk-2ECWEUHP.js';
4
+ import '../chunk-BEBR4OJD.js';
5
+ import '../chunk-WGG6GTKW.js';
6
+ import '../chunk-56KNHB4U.js';
7
7
  import '../chunk-PKBMQBKP.js';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
- import { sonorFetch } from '../chunk-3SDOQUUF.js';
3
- import '../chunk-VDF5DFWT.js';
4
- import '../chunk-AH5Q262S.js';
2
+ import { sonorFetch } from '../chunk-BEBR4OJD.js';
3
+ import '../chunk-WGG6GTKW.js';
4
+ import '../chunk-56KNHB4U.js';
5
5
  import '../chunk-PKBMQBKP.js';
6
6
  import { useState, useEffect } from 'react';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -1,13 +1,13 @@
1
1
  'use client';
2
2
  export { ContactTracking, useContactTracking } from '../chunk-P5GB6NEO.js';
3
- export { AnalyticsProvider, WebVitals, useAnalytics, useAnalyticsOptional, useTrackEvent } from '../chunk-YEMPUQVU.js';
3
+ export { AnalyticsProvider, WebVitals, useAnalytics, useAnalyticsOptional, useTrackEvent } from '../chunk-MKMD2HJW.js';
4
4
  export { trackConversion, trackEvent } from '../chunk-LCDVPAMR.js';
5
5
  import '../chunk-24QZEO3Q.js';
6
6
  import '../chunk-L2V5PUFN.js';
7
7
  import '../chunk-GJWI74ZZ.js';
8
8
  export { isCrossOriginFrame, isFramed, isTopFrameSameOrigin } from '../chunk-43OCZ3JA.js';
9
9
  import '../chunk-EKBEOXTH.js';
10
- import '../chunk-3SDOQUUF.js';
11
- import '../chunk-VDF5DFWT.js';
12
- import '../chunk-AH5Q262S.js';
10
+ import '../chunk-BEBR4OJD.js';
11
+ import '../chunk-WGG6GTKW.js';
12
+ import '../chunk-56KNHB4U.js';
13
13
  import '../chunk-PKBMQBKP.js';
@@ -12,7 +12,7 @@
12
12
  * in one place and left broken in seven.
13
13
  * `send-gate.test.ts` fails the build if a new direct call appears.
14
14
  *
15
- * Fleet, client SitemapSync and Engage also consult this gate. Local browser
15
+ * Fleet, client SitemapSync, chat and popups also consult this gate. Local browser
16
16
  * hosts are blocked regardless of configured production site identity. Node
17
17
  * build callers retain their existing behavior.
18
18
  *
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- import { NewsletterShell } from '../chunk-SC4MZGWZ.js';
3
2
  export { ArticleFAQ } from '../chunk-GKGSXUVQ.js';
3
+ import { NewsletterShell } from '../chunk-SC4MZGWZ.js';
4
4
  import { getAuthorSocialLinks, readingTimeMinutes } from '../chunk-FV2VD7WM.js';
5
5
  export { ClusterNavigation, ServiceCallout, ServiceCallouts } from '../chunk-FV2VD7WM.js';
6
6
  import '../chunk-GYF2ULVO.js';
@@ -15,7 +15,7 @@ import '../chunk-PKBMQBKP.js';
15
15
  import React, { useState, Suspense, useEffect } from 'react';
16
16
  import { jsx, jsxs } from 'react/jsx-runtime';
17
17
 
18
- var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-J6QSAGGP.js'));
18
+ var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-TC5542ZG.js'));
19
19
  function NewsletterWidget({
20
20
  title = "Subscribe to Our Newsletter",
21
21
  description = "Get the latest posts delivered straight to your inbox.",
@@ -2,12 +2,13 @@ import { readingTimeMinutes, ServiceCallouts, ClusterNavigation, getAuthorSocial
2
2
  export { ClusterNavigation } from '../chunk-FV2VD7WM.js';
3
3
  import { widgetStyle, widgetTitleStyle } from '../chunk-GYF2ULVO.js';
4
4
  import { resolvePublicationSiteUrl, addExternalLinkTargets } from '../chunk-L5UOHS6E.js';
5
- import { fetchArticleBySlug, fetchRelatedArticles, fetchArticleCategories, getTopicCluster } from '../chunk-TXBAOEKG.js';
5
+ import { fetchArticleBySlug, fetchRelatedArticles, fetchArticleCategories, getTopicCluster } from '../chunk-PKGN32AU.js';
6
6
  export { articleTableCss, wrapArticleTables } from '../chunk-Y3INC4QJ.js';
7
7
  import { resolveArticleArtwork, articleArtworkImageStyle } from '../chunk-QXMIKDOL.js';
8
8
  export { resolveArticleArtwork } from '../chunk-QXMIKDOL.js';
9
9
  import { createPublicationRoutes, articleCategorySlug } from '../chunk-WMVK77ND.js';
10
10
  export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolvePublicationUrl } from '../chunk-WMVK77ND.js';
11
+ import '../chunk-VWWITFWM.js';
11
12
  import { withSiteParam } from '../chunk-MJP63SSS.js';
12
13
  import '../chunk-X6F6SO4S.js';
13
14
  import '../chunk-MH2DSGC6.js';
@@ -132,7 +133,7 @@ async function Article({
132
133
  ...item,
133
134
  answer: addExternalLinkTargets(item.answer || "", siteUrlResolved)
134
135
  })) ?? faqRaw;
135
- const { ArticleViewTracker } = await import('../ArticleViewTracker-GMHYLLLZ.js');
136
+ const { ArticleViewTracker } = await import('../ArticleViewTracker-GFOAXFV7.js');
136
137
  if (children) {
137
138
  return /* @__PURE__ */ jsxs(Fragment, { children: [
138
139
  /* @__PURE__ */ jsx(ArticleViewTracker, { slug: post.slug, site }),
@@ -1,7 +1,8 @@
1
- export { FEED_DEFAULT_ITEMS, NEWS_SITEMAP_MAX_URLS, NEWS_SITEMAP_WINDOW_MS, SEO_LIMITS, buildNewsSitemapXml, cdata, generateAllArticleSchemas, generateArticleCategoryMetadata, generateArticleListSchema, generateArticleMetadata, generateArticleSchema, generateArticleSitemap, generateArticleStaticParams, generateAtomFeed, generateAuthorPageMetadata, generateAuthorStaticParams, generateBreadcrumbSchema, generateCategoryStaticParams, generateClusterArticleSchema, generateClusterBreadcrumbSchema, generateClusterItemListSchema, generateClusterLandingSchema, generateClusterPageMetadata, generateFaqSchema, generateHowToSchema, generateNewsSitemap, generatePublicationMetadata, generateRssFeed, getAllArticleSlugs, getAllArticles, getAllAuthorSlugs, getArticle, getArticleCategories, getAuthorBySlug, getAuthorPosts, getClusterNavigation, getPostsByCategory, getRelatedInsights, getTopicCluster, getTopicClusters, recentNewsPosts, requireArticle, sanitizeExcerpt, validateArticleSeo, validateMetaDescription, validateSeoTitle } from '../chunk-TXBAOEKG.js';
1
+ export { FEED_DEFAULT_ITEMS, NEWS_SITEMAP_MAX_URLS, NEWS_SITEMAP_WINDOW_MS, SEO_LIMITS, buildNewsSitemapXml, cdata, generateAllArticleSchemas, generateArticleCategoryMetadata, generateArticleListSchema, generateArticleMetadata, generateArticleSchema, generateArticleSitemap, generateArticleStaticParams, generateAtomFeed, generateAuthorPageMetadata, generateAuthorStaticParams, generateBreadcrumbSchema, generateCategoryStaticParams, generateClusterArticleSchema, generateClusterBreadcrumbSchema, generateClusterItemListSchema, generateClusterLandingSchema, generateClusterPageMetadata, generateFaqSchema, generateHowToSchema, generateNewsSitemap, generatePublicationMetadata, generateRssFeed, getAllArticleSlugs, getAllArticles, getAllAuthorSlugs, getArticle, getArticleCategories, getAuthorBySlug, getAuthorPosts, getClusterNavigation, getPostsByCategory, getRelatedInsights, getTopicCluster, getTopicClusters, recentNewsPosts, requireArticle, sanitizeExcerpt, validateArticleSeo, validateMetaDescription, validateSeoTitle } from '../chunk-PKGN32AU.js';
2
2
  export { articleTableCss, wrapArticleTables } from '../chunk-Y3INC4QJ.js';
3
3
  export { authorEntityId, generateArticleAuthorNode, generateAuthorPersonSchema, generateAuthorSchema, resolveArticleArtwork, withArticleAuthorIdentity } from '../chunk-QXMIKDOL.js';
4
4
  export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolvePublicationUrl } from '../chunk-WMVK77ND.js';
5
+ import '../chunk-VWWITFWM.js';
5
6
  import '../chunk-MJP63SSS.js';
6
7
  import '../chunk-X6F6SO4S.js';
7
8
  import '../chunk-MH2DSGC6.js';