@sonordev/site-kit 7.1.1 → 7.2.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 (282) hide show
  1. package/AGENTS.md +3 -3
  2. package/CHANGELOG.md +68 -3426
  3. package/README.md +9 -8
  4. package/agent-manifest.json +12 -4
  5. package/dist/{AnalyticsProvider-3MI5RCTL.js → AnalyticsProvider-SLFFBRPE.js} +4 -4
  6. package/dist/{ArticleViewTracker-CMBSJR3N.js → ArticleViewTracker-TM5AMGN2.js} +3 -3
  7. package/dist/{BlocksPopup-X3OAAK2L.js → BlocksPopup-YJNJIVPO.js} +5 -5
  8. package/dist/ChatWidget-XKOSH66S.js +17 -0
  9. package/dist/{FileField-QRSEGO6D.js → FileField-CI4UL5SH.js} +3 -3
  10. package/dist/{FormSpotlight-XKV7VTN4.js → FormSpotlight-F2AAEGBN.js} +20 -6
  11. package/dist/{FormStage-C3YGYAUZ.js → FormStage-BI5R5CNC.js} +27 -7
  12. package/dist/ManagedForm-G6COGHXL.js +16 -0
  13. package/dist/{ManagedNewsletterForm-LPIKGJF4.js → ManagedNewsletterForm-BO3WCGXX.js} +7 -5
  14. package/dist/{SignalCore-ICXXZBYI.js → SignalCore-ZA6WHKBR.js} +3 -3
  15. package/dist/SiteChat-YJADDTKG.js +5 -0
  16. package/dist/{SiteDesignReporter-A7MS2CIP.js → SiteDesignReporter-5YAW36AQ.js} +5 -5
  17. package/dist/SitePopups-ST5PMKZE.js +10 -0
  18. package/dist/SitemapSync-RJTEBINX.js +8 -0
  19. package/dist/SitemapSync.d.ts +1 -1
  20. package/dist/_client/booking-widget.js +5 -5
  21. package/dist/_client/testimonial-section.d.ts +1 -1
  22. package/dist/affiliates/api.d.ts +1 -1
  23. package/dist/affiliates/index.js +3 -3
  24. package/dist/analytics/AnalyticsProvider.d.ts +1 -1
  25. package/dist/analytics/index.js +4 -4
  26. package/dist/analytics/send-gate.d.ts +13 -26
  27. package/dist/articles/Article.d.ts +1 -1
  28. package/dist/articles/ArticleList.d.ts +1 -1
  29. package/dist/articles/ClusterLandingPage.d.ts +2 -2
  30. package/dist/articles/PublicationLayout.d.ts +1 -1
  31. package/dist/articles/PublicationSidebar.d.ts +1 -1
  32. package/dist/articles/RelatedPosts.d.ts +1 -1
  33. package/dist/articles/author-schema.d.ts +1 -1
  34. package/dist/articles/excerpt.d.ts +3 -4
  35. package/dist/articles/index.d.ts +2 -2
  36. package/dist/articles/index.js +2 -2
  37. package/dist/articles/news-sitemap.d.ts +1 -1
  38. package/dist/articles/processArticleHtml.d.ts +1 -1
  39. package/dist/articles/server-core.d.ts +4 -4
  40. package/dist/articles/server-ui.js +3 -2
  41. package/dist/articles/server.d.ts +4 -4
  42. package/dist/articles/server.js +2 -1
  43. package/dist/articles/types.d.ts +1 -1
  44. package/dist/{engage → chat}/ChatWidget.d.ts +8 -7
  45. package/dist/{engage → chat}/EchoUiActions.d.ts +4 -4
  46. package/dist/chat/SiteChat.d.ts +25 -0
  47. package/dist/{engage → chat}/brand-color.d.ts +2 -2
  48. package/dist/{engage → chat}/chat-messages.d.ts +1 -1
  49. package/dist/{engage → chat}/echo-config.d.ts +1 -1
  50. package/dist/chat/index.d.ts +10 -6
  51. package/dist/chat/index.js +14 -8
  52. package/dist/{engage → chat}/launcher-placement.d.ts +1 -7
  53. package/dist/{engage → chat}/socket-loader.d.ts +2 -2
  54. package/dist/chat/types.d.ts +136 -0
  55. package/dist/chunk-27FISYK4.js +4 -0
  56. package/dist/{chunk-QPEEKFCA.js → chunk-4NTBQNHA.js} +249 -80
  57. package/dist/{chunk-RK7GF7PQ.js → chunk-5V2V5C3Y.js} +2 -4
  58. package/dist/{chunk-ICFRH2ED.js → chunk-5YCEMV2L.js} +1 -1
  59. package/dist/{chunk-V4HUSHZO.js → chunk-64DKGVEI.js} +41 -7
  60. package/dist/{chunk-GLHQ3LRO.js → chunk-6U3VLV2C.js} +1 -1
  61. package/dist/{chunk-ZETJTCMV.js → chunk-BC4Y3S3D.js} +1 -1
  62. package/dist/{chunk-JSZN6LDZ.js → chunk-BF7TZYC3.js} +38 -31
  63. package/dist/{chunk-EFPS56JA.js → chunk-BKY2ZNM7.js} +1 -1
  64. package/dist/{chunk-AQSNPZY4.js → chunk-C2FZBUSS.js} +80 -1
  65. package/dist/{chunk-H42PZKVC.js → chunk-CF5QNFYU.js} +2 -2
  66. package/dist/{chunk-JC7KXNNM.js → chunk-D5DCBD4Y.js} +2 -2
  67. package/dist/{chunk-PXZ7LAOY.js → chunk-D6ZC7XKZ.js} +2 -2
  68. package/dist/chunk-EJVQJCG5.js +370 -0
  69. package/dist/{chunk-6OL23QYD.js → chunk-F24FNCTK.js} +1 -1
  70. package/dist/{chunk-NEKEH4CK.js → chunk-FR6BYFPC.js} +53 -21
  71. package/dist/{chunk-KOPVJQ2P.js → chunk-GEXT7BTE.js} +1 -1
  72. package/dist/{chunk-ZAWANWUS.js → chunk-GGORNBSC.js} +18 -6
  73. package/dist/{chunk-DUQMSNF2.js → chunk-HGFAEDG3.js} +1 -1
  74. package/dist/chunk-HODO5BX5.js +28 -0
  75. package/dist/chunk-HW7B43E5.js +14 -0
  76. package/dist/{chunk-EQBZ24VH.js → chunk-IAM3D3RL.js} +43 -24
  77. package/dist/{chunk-ODADQM6Z.js → chunk-JJ3DELUL.js} +2 -2
  78. package/dist/{chunk-542MIHNP.js → chunk-JMLK6MH7.js} +1 -1
  79. package/dist/{chunk-7FWA3I6A.js → chunk-JWTQS5F5.js} +1 -1
  80. package/dist/{chunk-OUNRFXDC.js → chunk-K4ZHAURD.js} +1 -1
  81. package/dist/chunk-NV72HZ4W.js +45 -0
  82. package/dist/{chunk-4Y5FWDPM.js → chunk-NZ4RXN3G.js} +55 -7
  83. package/dist/chunk-OWZ7ATLZ.js +187 -0
  84. package/dist/{chunk-TXBAOEKG.js → chunk-PKGN32AU.js} +5 -4
  85. package/dist/chunk-Q6E4OPGG.js +40 -0
  86. package/dist/{chunk-J4D6ZXRW.js → chunk-QL6XNPSD.js} +3 -3
  87. package/dist/{chunk-HAG4YIZY.js → chunk-R46IQIGK.js} +6 -6
  88. package/dist/{chunk-R3VKF43H.js → chunk-RPZ7OQGD.js} +1 -1
  89. package/dist/{chunk-Q3S26EQA.js → chunk-S54ECQGY.js} +1 -1
  90. package/dist/{chunk-JIL5VY2R.js → chunk-VHKEF5ZB.js} +1 -1
  91. package/dist/{chunk-ILAW3XKD.js → chunk-VO3JYRT5.js} +43 -29
  92. package/dist/chunk-VWWITFWM.js +300 -0
  93. package/dist/{chunk-OPRBF7VE.js → chunk-ZTLMPUO6.js} +3 -2
  94. package/dist/client/index.js +3 -3
  95. package/dist/cms/CmsPreview.d.ts +2 -2
  96. package/dist/cms/index.d.ts +3 -3
  97. package/dist/cms/server-api.d.ts +1 -1
  98. package/dist/cms/types.d.ts +1 -1
  99. package/dist/commerce/EventCheckout.d.ts +1 -1
  100. package/dist/commerce/EventsAgenda.d.ts +3 -3
  101. package/dist/commerce/api.d.ts +1 -1
  102. package/dist/commerce/index.js +4 -4
  103. package/dist/commerce/server.d.ts +3 -4
  104. package/dist/contracts/color.d.ts +1 -1
  105. package/dist/contracts/entries.d.ts +1 -1
  106. package/dist/contracts/error-page.d.ts +183 -0
  107. package/dist/contracts/fleet.d.ts +9 -9
  108. package/dist/contracts/forms.d.ts +4 -10
  109. package/dist/contracts/llms.d.ts +2 -1
  110. package/dist/contracts/portfolio.d.ts +11 -15
  111. package/dist/contracts/proposal-sitemap.d.ts +130 -0
  112. package/dist/contracts/schema-placeholders.d.ts +87 -0
  113. package/dist/contracts/seo-meta.d.ts +11 -12
  114. package/dist/contracts/seo-pages.d.ts +12 -18
  115. package/dist/contracts/site-cache.d.ts +4 -4
  116. package/dist/contracts/sites-normalize.d.ts +2 -4
  117. package/dist/contracts/sites.d.ts +3 -5
  118. package/dist/contracts/slot-content.d.ts +2 -2
  119. package/dist/contracts/slots.d.ts +6 -6
  120. package/dist/contracts/voice.d.ts +56 -0
  121. package/dist/contracts/website.d.ts +2 -2
  122. package/dist/engage/EngageWidget.d.ts +13 -12
  123. package/dist/engage/index.d.ts +10 -9
  124. package/dist/engage/index.js +31 -35
  125. package/dist/engage/types.d.ts +19 -244
  126. package/dist/fleet/FleetHeartbeat.d.ts +2 -2
  127. package/dist/fleet/index.js +4 -4
  128. package/dist/forms/FormEnhancer.d.ts +25 -12
  129. package/dist/forms/FormSpotlight.d.ts +2 -2
  130. package/dist/forms/ManagedForm.d.ts +1 -1
  131. package/dist/forms/ServerForm.d.ts +11 -10
  132. package/dist/forms/StaticForm.d.ts +4 -2
  133. package/dist/forms/field-autocomplete.d.ts +28 -0
  134. package/dist/forms/field-interactions.d.ts +2 -2
  135. package/dist/forms/form-dom-values.d.ts +42 -0
  136. package/dist/forms/form-loaded-at.d.ts +2 -2
  137. package/dist/forms/formsApi.d.ts +2 -2
  138. package/dist/forms/index.d.ts +1 -1
  139. package/dist/forms/index.js +11 -9
  140. package/dist/forms/server.d.ts +1 -1
  141. package/dist/forms/server.js +6 -4
  142. package/dist/forms/static.js +3 -2
  143. package/dist/forms/submitForm.d.ts +9 -2
  144. package/dist/forms/types.d.ts +44 -5
  145. package/dist/forms/useForm.d.ts +21 -4
  146. package/dist/forms/webmcp.d.ts +38 -0
  147. package/dist/images/ManagedFavicon.d.ts +1 -1
  148. package/dist/images/ManagedImage.d.ts +4 -4
  149. package/dist/images/api.d.ts +1 -1
  150. package/dist/images/index.d.ts +2 -2
  151. package/dist/images/index.js +4 -4
  152. package/dist/index.d.ts +4 -1
  153. package/dist/index.js +1 -1
  154. package/dist/landing/contract.d.ts +3 -4
  155. package/dist/layout/SiteKitClientProviders.d.ts +4 -4
  156. package/dist/layout/SiteKitLayout.d.ts +11 -11
  157. package/dist/layout/client.d.ts +4 -4
  158. package/dist/layout/client.js +7 -7
  159. package/dist/layout/index.js +8 -8
  160. package/dist/layout/types.d.ts +7 -6
  161. package/dist/llms/SpeakableSchema.d.ts +2 -2
  162. package/dist/llms/agent-access.d.ts +2 -2
  163. package/dist/llms/aiRobots.d.ts +4 -4
  164. package/dist/llms/api.d.ts +2 -2
  165. package/dist/llms/contract.js +1 -1
  166. package/dist/llms/generateLLMsTxt.d.ts +1 -1
  167. package/dist/llms/index.js +6 -6
  168. package/dist/llms/links.d.ts +1 -1
  169. package/dist/llms/revalidate.d.ts +1 -1
  170. package/dist/llms/seo-revalidate.d.ts +2 -3
  171. package/dist/llms/types.d.ts +6 -6
  172. package/dist/llms/writeLLMsTxt.d.ts +10 -10
  173. package/dist/manifest/index.d.ts +8 -8
  174. package/dist/maps/index.js +3 -3
  175. package/dist/mcp/WebMcpTools.d.ts +1 -1
  176. package/dist/mcp/index.js +2 -14
  177. package/dist/mcp/report.d.ts +2 -2
  178. package/dist/mcp/serverCard.d.ts +1 -1
  179. package/dist/mcp/sonor.d.ts +5 -6
  180. package/dist/mcp/sonor.js +14 -11
  181. package/dist/mcp/transport.d.ts +1 -2
  182. package/dist/mcp/types.d.ts +4 -5
  183. package/dist/motion/engine.d.ts +2 -3
  184. package/dist/motion/failsafe.d.ts +1 -2
  185. package/dist/motion/gsap.d.ts +2 -2
  186. package/dist/motion/three.d.ts +1 -1
  187. package/dist/og/config.d.ts +4 -4
  188. package/dist/og/contrast.d.ts +2 -2
  189. package/dist/og/pages.d.ts +5 -5
  190. package/dist/og/route-fit.d.ts +2 -2
  191. package/dist/og/route.d.ts +1 -2
  192. package/dist/og/template.d.ts +1 -1
  193. package/dist/proxy/index.d.ts +2 -2
  194. package/dist/proxy/securityHeaders.d.ts +10 -12
  195. package/dist/redirects/index.d.ts +7 -7
  196. package/dist/reputation/TestimonialSection.d.ts +1 -1
  197. package/dist/reputation/api.d.ts +1 -1
  198. package/dist/revalidate/index.js +2 -2
  199. package/dist/robots/index.d.ts +5 -5
  200. package/dist/robots/indexnow.d.ts +2 -3
  201. package/dist/seo/ManagedScripts.d.ts +2 -2
  202. package/dist/seo/client.js +4 -4
  203. package/dist/seo/getManagedMetadata.d.ts +1 -1
  204. package/dist/seo/groundingSchema.d.ts +2 -2
  205. package/dist/seo/index.js +15 -8
  206. package/dist/seo/llms/contract.js +1 -1
  207. package/dist/seo/llms.js +6 -6
  208. package/dist/seo/register-sitemap-cli-impl.d.ts +1 -1
  209. package/dist/seo/register-sitemap-cli.d.ts +1 -1
  210. package/dist/seo/register-sitemap-cli.js +2 -2
  211. package/dist/seo/schema-filter.d.ts +5 -6
  212. package/dist/seo/server-api.d.ts +1 -1
  213. package/dist/seo/sitemap.js +4 -4
  214. package/dist/seo/types.d.ts +4 -4
  215. package/dist/seo/withManagedMetadata.d.ts +4 -4
  216. package/dist/server/index.js +2 -2
  217. package/dist/server/mint-site-token.d.ts +1 -2
  218. package/dist/server/server-fetch.d.ts +5 -5
  219. package/dist/shared/build-entries.d.ts +4 -4
  220. package/dist/shared/dialog.d.ts +27 -0
  221. package/dist/shared/frame.d.ts +8 -9
  222. package/dist/shared/fresh-fetch.d.ts +1 -2
  223. package/dist/shared/identity.d.ts +1 -1
  224. package/dist/shared/layers.d.ts +7 -0
  225. package/dist/shared/mid-form.d.ts +53 -0
  226. package/dist/shared/next-files.d.ts +1 -1
  227. package/dist/shared/publishCredential.d.ts +1 -1
  228. package/dist/shared/reporting-gate.d.ts +1 -1
  229. package/dist/shared/uuid.d.ts +1 -2
  230. package/dist/shared/version.d.ts +1 -1
  231. package/dist/shared/visual-viewport-gap.d.ts +3 -3
  232. package/dist/signal/index.js +2 -2
  233. package/dist/signal/types.d.ts +1 -1
  234. package/dist/site-config/index.d.ts +2 -2
  235. package/dist/sitemap/index.d.ts +13 -13
  236. package/dist/sitemap/index.js +4 -4
  237. package/dist/sitemap/shared.d.ts +3 -3
  238. package/dist/sites/site-param.d.ts +2 -2
  239. package/dist/slots/ManagedRichText.d.ts +1 -1
  240. package/dist/slots/ManagedSlot.d.ts +1 -1
  241. package/dist/slots/index.d.ts +1 -3
  242. package/dist/{socket-loader-R24ZSRSQ.js → socket-loader-CGIPEG74.js} +1 -1
  243. package/dist/sync/index.js +5 -5
  244. package/dist/types.d.ts +4 -2
  245. package/dist/website/BlocksPopup.d.ts +1 -1
  246. package/dist/website/PopupBlocks.d.ts +8 -6
  247. package/dist/website/SitePopups.d.ts +25 -0
  248. package/dist/website/images.js +4 -4
  249. package/dist/website/index.js +6 -6
  250. package/dist/website/popup-rules.d.ts +46 -0
  251. package/dist/website/popup-types.d.ts +113 -0
  252. package/dist/website/popups.d.ts +2 -6
  253. package/dist/website/popups.js +6 -14
  254. package/dist/{writeLLMsTxt-QR23OQUE.js → writeLLMsTxt-OV24LQVL.js} +3 -3
  255. package/docs/MIGRATING-TO-7.md +50 -22
  256. package/docs.json +2 -1
  257. package/package.json +2 -2
  258. package/src/admin-auth/README.md +3 -3
  259. package/src/analytics/README.md +9 -11
  260. package/src/articles/README.md +10 -7
  261. package/src/{engage → chat}/README.md +63 -62
  262. package/src/cta-bar/README.md +11 -11
  263. package/src/forms/README.md +60 -12
  264. package/src/layout/README.md +8 -5
  265. package/src/llms/README.md +3 -3
  266. package/src/mcp/README.md +7 -7
  267. package/src/motion/README.md +1 -1
  268. package/src/og/README.md +26 -27
  269. package/src/proxy/README.md +14 -14
  270. package/src/seo/README.md +4 -2
  271. package/src/slots/README.md +1 -1
  272. package/src/sync/README.md +10 -0
  273. package/src/website/README.md +133 -0
  274. package/dist/ChatWidget-JMFBXJ75.js +0 -15
  275. package/dist/EngageWidget-A3QKZ3SU.js +0 -11
  276. package/dist/ManagedForm-2GSSDJPP.js +0 -14
  277. package/dist/SitemapSync-4U654SEA.js +0 -8
  278. package/dist/chunk-B73QPZPH.js +0 -837
  279. package/dist/chunk-NDF4A5JM.js +0 -37
  280. package/dist/chunk-RTMMHTEQ.js +0 -100
  281. package/dist/engage/DesignRenderer.d.ts +0 -57
  282. package/dist/engage/element-rules.d.ts +0 -38
@@ -4,17 +4,16 @@
4
4
  * Single source of truth for "is this machine-generated seo_pages.managed_title
5
5
  * / managed_meta_description fit to ship?". site-kit applies it at render time
6
6
  * (getManagedMetadata falls back to the page's own title/description), and
7
- * signal-api imports it (`src/shared/utils/seo-meta-quality.util.ts`) to gate
8
- * every generated title before it's written, so the two can't disagree.
7
+ * Signal applies it to every generated title before it's written, so the two
8
+ * can't disagree.
9
9
  *
10
- * Why it exists (2026-09-15): Signal's meta generator used the raw domain as
11
- * the brand whenever it could not resolve one, so ~500 managed titles across
12
- * 20+ projects shipped as "Apartments for Rent | abbeyglenapts.com", were
13
- * hard-cut at 60 chars ("… | reinhartheatingandcooli"), lost the suffix to a
14
- * word-boundary cut ("Contact Reinhart Heating and Cooling |"), or had the
15
- * model rebuild a brand out of the domain ("About SSO Shkosh Apartments | SSO
16
- * Shkosh" for ssoshkoshapts.com — the brand is SS Oshkosh Apartments). Sites
17
- * rendered them verbatim.
10
+ * Why it exists: a meta generator that uses the raw domain as the brand when it
11
+ * can't resolve one ships titles like "Apartments for Rent |
12
+ * maplecourtapts.com", hard-cuts them at 60 chars ("… |
13
+ * brightsideheatingandcooli"), loses the suffix to a word-boundary cut
14
+ * ("Contact Brightside Heating and Cooling |"), or rebuilds a brand out of the
15
+ * domain ("About BBE Llis Apartments | BBE Llis" for bbellisapts.com, when the
16
+ * brand is BB Ellis Apartments). Sites render them verbatim.
18
17
  *
19
18
  * Every rule derives from the site's own identity (its hosts and brand), so
20
19
  * there is no list of bad strings to maintain. Pure string logic — no I/O, no
@@ -24,7 +23,7 @@
24
23
  export declare const SEO_META_CONTRACT_VERSION: 1;
25
24
  /** Who the site is. Hosts come from the project/site config, the brand from the resolved business name — never from the domain. */
26
25
  export interface MetaIdentity {
27
- /** The site's brand, e.g. "SS Oshkosh Apartments". */
26
+ /** The site's brand, e.g. "BB Ellis Apartments". */
28
27
  brand?: string | null;
29
28
  /** Other correct spellings of the brand. */
30
29
  brandAliases?: Array<string | null | undefined>;
@@ -34,7 +33,7 @@ export interface MetaIdentity {
34
33
  export type TitleProblem = 'empty' | 'placeholder' | 'dangling-separator' | 'hostname' | 'mangled-brand';
35
34
  export type DescriptionProblem = 'empty' | 'hostname' | 'mangled-brand' | 'truncated';
36
35
  export type SuffixProblem = 'hostname' | 'mangled-brand';
37
- /** "https://www.AbbeyGlenApts.com:443/x" → "abbeyglenapts.com". Null for anything that isn't a host (no dot, or words). */
36
+ /** "https://www.MapleCourtApts.com:443/x" → "maplecourtapts.com". Null for anything that isn't a host (no dot, or words). */
38
37
  export declare function metaHost(value: string | null | undefined): string | null;
39
38
  /** True when the text names the brand (an alias, or either one's core) word for word. */
40
39
  export declare function namesBrand(text: string, id: MetaIdentity): boolean;
@@ -3,13 +3,10 @@
3
3
  *
4
4
  * Single source of truth for choosing ONE seo_pages row when a (project_id,
5
5
  * path/url) lookup matches several, and for scoping a project's rows to one
6
- * host. site-kit (`@sonordev/site-kit/seo/pages/contract`), sonor-api
7
- * (`src/modules/seo/seo-page-resolve.util.ts`) and signal-api
8
- * (`src/shared/utils/seo-page-pick.util.ts`) all import this; none keeps a
9
- * copy.
6
+ * host. site-kit (`@sonordev/site-kit/seo/pages/contract`) and both Sonor
7
+ * APIs import this; none keeps a copy.
10
8
  *
11
- * seo_pages identity became (project_id, site, url) in sonor-api migration
12
- * 20260702150000_seo_pages_per_site_identity.sql: a multi-site project (one
9
+ * seo_pages identity is (project_id, site, url): a multi-site project (one
13
10
  * Sonor project hosting many domains) keeps one row PER SUB-SITE HOST for
14
11
  * shared paths like `/` or `/contact`. Any path/url lookup can therefore match
15
12
  * several rows — `.single()`/`.maybeSingle()` error on them (PGRST116) — so
@@ -26,11 +23,9 @@ export declare const SEO_PAGES_CONTRACT_VERSION: 1;
26
23
  *
27
24
  * Retired pages are kept as tombstones (status='removed') so their history and
28
25
  * redirects survive, which means every public read has to opt out of them
29
- * explicitly. Three reads in llms-content.service.ts never did, and the sitemap
30
- * sync's removal flag was write-only for as long as the code existed: on
31
- * 2026-09-20 upforge.io's llms.txt — the file handed straight to AI crawlers —
32
- * was 32% dead URLs, advertising service areas in Atlanta, Detroit and Tampa
33
- * that the business has never served.
26
+ * explicitly. A read that forgets serves dead URLs: an llms.txt, the file
27
+ * handed straight to AI crawlers, ends up advertising pages the business
28
+ * retired long ago.
34
29
  *
35
30
  * Null-safe by design: `status` is nullable with an 'active' default, so a row
36
31
  * whose status was explicitly nulled stays live rather than vanishing from the
@@ -80,13 +75,12 @@ export declare function matchSitemapEntryRow<T extends SeoPageRowLike>(candidate
80
75
  * that belongs to `site`, keeping at most one row per path.
81
76
  *
82
77
  * Why this exists: a multi-site project (one Sonor project hosting many
83
- * domains — bd-aec.com plus 48 sibling domains, truepowersystems.com plus its
84
- * state microsites) holds one row PER HOST for shared paths like `/` and
85
- * `/terms`. Any project-wide read that dedupes by path alone therefore keeps an
86
- * ARBITRARY host's row. Observed 2026-08-25: bd-aec.com's llms.txt described
87
- * `/` with soqwriters.com's homepage copy and `/terms` with bd-charlotte.com's,
88
- * and which sibling won changed every time a neighbour rebuilt, because the tie
89
- * among same-path rows is broken by whatever order Postgres returns.
78
+ * domains, e.g. example.com plus dozens of city microsites) holds one row PER
79
+ * HOST for shared paths like `/` and `/terms`. Any project-wide read that
80
+ * dedupes by path alone therefore keeps an ARBITRARY host's row: example.com's
81
+ * llms.txt can describe `/` with a sibling's homepage copy, and which sibling
82
+ * wins changes every time a neighbour rebuilds, because the tie among
83
+ * same-path rows is broken by whatever order Postgres returns.
90
84
  *
91
85
  * Rules, per path, via `matchSitemapEntryRow`:
92
86
  * - this host's row wins outright
@@ -2,11 +2,11 @@
2
2
  * How Sonor refreshes a site's cached pages when content changes.
3
3
  *
4
4
  * A site serves cached pages and caches every fetch from Sonor. When someone
5
- * edits content in Sonor, sonor-api POSTs the paths and cache tags that
5
+ * edits content in Sonor, Sonor POSTs the paths and cache tags that
6
6
  * changed to the site's revalidation route, authenticated with the project's
7
7
  * API key, and the site regenerates just those. site-kit tags its fetches with
8
8
  * these names and serves the route (`@sonordev/site-kit/revalidate`);
9
- * sonor-api sends them. Single source of truth for the names on both sides:
9
+ * Sonor sends them. Single source of truth for the names on both sides:
10
10
  * never spell a tag as a string literal in either.
11
11
  */
12
12
  /** Where the revalidation route lives on every site. */
@@ -29,7 +29,7 @@ export declare const SITE_CACHE_TAGS: {
29
29
  readonly portfolio: 'portfolio';
30
30
  };
31
31
  export type SiteCacheTag = (typeof SITE_CACHE_TAGS)[keyof typeof SITE_CACHE_TAGS];
32
- /** The body sonor-api POSTs to the revalidation route. */
32
+ /** The body Sonor POSTs to the revalidation route. */
33
33
  export interface SiteRevalidatePayload {
34
34
  /** Local paths to regenerate, e.g. `['/services/roofing']`. */
35
35
  paths?: string[];
@@ -39,7 +39,7 @@ export interface SiteRevalidatePayload {
39
39
  revalidateAll?: boolean;
40
40
  /**
41
41
  * Only check that the route is installed and the key matches; nothing is
42
- * regenerated. sonor-api pings after it registers a site's route, so it
42
+ * regenerated. Sonor pings after it registers a site's route, so it
43
43
  * knows whether an edit goes live in seconds or waits for the cache to age out.
44
44
  */
45
45
  ping?: boolean;
@@ -14,9 +14,7 @@
14
14
  * pushed those entries over their bundle budgets.
15
15
  *
16
16
  * `./sites` re-exports this, so `@sonordev/contracts/sites` (and site-kit's
17
- * `sites/contract`) carry it too. The Nest APIs import it from there
18
- * (sonor-api `src/common/utils/site-host.ts`, signal-api
19
- * `src/shared/utils/seo-page-pick.util.ts`).
17
+ * `sites/contract`) carry it too. The Sonor APIs import it from there.
20
18
  *
21
19
  * Pure string logic only (no Node built-ins) so it is safe in the browser.
22
20
  */
@@ -24,7 +22,7 @@
24
22
  * normalizeSiteHost — canonical normalizer for a sub-site host value before it
25
23
  * is persisted or used as a filter.
26
24
  *
27
- * `https://OhioPowerStudies.com:3000/path` → `ohiopowerstudies.com`
25
+ * `https://Ohio.Example.com:3000/path` → `ohio.example.com`
28
26
  *
29
27
  * Lowercases, strips protocol, keeps host only (drops path + query), strips
30
28
  * port (rollups span dev/prod) and the FQDN root dot. Returns null for
@@ -2,10 +2,8 @@
2
2
  * @sonordev/contracts/sites — Multi-site "site" dimension host contract (v1)
3
3
  *
4
4
  * Single source of truth for normalizing and comparing sub-site host values
5
- * (the multi-site `site` dimension, see CLAUDE.md). site-kit, sonor-api
6
- * (`src/common/utils/site-host.ts`) and signal-api
7
- * (`src/shared/utils/seo-page-pick.util.ts`) all import it, so there's no
8
- * copy to drift.
5
+ * (the multi-site `site` dimension). site-kit and both Sonor APIs import it,
6
+ * so there's no copy to drift.
9
7
  *
10
8
  * Pure string logic only (no Node built-ins) so it is safe in the browser:
11
9
  * site-kit itself normalizes `__SITE_KIT_SITE__` with `normalizeSiteHost`.
@@ -28,7 +26,7 @@ export declare function stripWww(host: string): string;
28
26
  */
29
27
  export declare function sameSite(a: string | null | undefined, b: string | null | undefined): boolean;
30
28
  /**
31
- * Host of a full URL ("https://ohiopowerstudies.com/x" → "ohiopowerstudies.com"),
29
+ * Host of a full URL ("https://ohio.example.com/x" → "ohio.example.com"),
32
30
  * null for site-relative paths ("/services") and unparseable input.
33
31
  */
34
32
  export declare function hostFromUrl(value: string | null | undefined): string | null;
@@ -4,7 +4,7 @@
4
4
  * The pure half of the slots contract: content types, value validation
5
5
  * (normalizeSlotValue), safe links, and the rich-text subset parser. No
6
6
  * crypto, so the dashboard can import it in the browser to validate and
7
- * preview exactly what sonor-api will accept and site-kit will render.
7
+ * preview exactly what the Sonor API will accept and site-kit will render.
8
8
  * `@sonordev/contracts/slots` re-exports all of it next to the signing.
9
9
  */
10
10
  /**
@@ -66,7 +66,7 @@ export type SlotValueResult = {
66
66
  /**
67
67
  * Validate and normalize what an editor (or Signal) submits for a slot of
68
68
  * `type`, returning the canonical `content` + `value` to store and sign.
69
- * The single rule for "what a valid slot of this type is": sonor-api runs it
69
+ * The single rule for "what a valid slot of this type is": the Sonor API runs it
70
70
  * on every write and verifySlotContent re-runs it on every read.
71
71
  */
72
72
  export declare function normalizeSlotValue(type: SlotContentType, input: {
@@ -3,23 +3,23 @@
3
3
  *
4
4
  * Single source of truth for the slot payload shape, value validation, the
5
5
  * rich-text subset, and content signing, shared by site-kit (verify + render),
6
- * sonor-api (validate + sign) and the dashboard (preview). Node only: it signs
6
+ * the Sonor API (validate + sign) and the dashboard (preview). Node only: it signs
7
7
  * with `crypto`.
8
8
  *
9
9
  * Security model: every SlotContent is HMAC-signed with the project API key.
10
10
  * site-kit verifies before rendering and falls back to the developer's static
11
11
  * content on any mismatch, so platform-originated content carries provenance
12
- * end to end. See docs/SITE-KIT-3.0-SPEC-SLOTS.md and docs/WEBSITE-CMS.md.
12
+ * end to end.
13
13
  *
14
14
  * v1 (site-kit ≤ 7.0) is plain text only. v2 adds rich text, links and lists,
15
- * and signs the structured value too. sonor-api serves both: a v1 request gets
15
+ * and signs the structured value too. Sonor serves both: a v1 request gets
16
16
  * text slots signed the v1 way and null for everything else.
17
17
  */
18
18
  import { type SlotContentType, type SlotValue } from './slot-content';
19
19
  export * from './slot-content';
20
20
  /** The version this package speaks. Bump on breaking payload changes. */
21
21
  export declare const SLOTS_CONTRACT_VERSION = 2;
22
- /** Versions sonor-api still serves. */
22
+ /** Versions Sonor still serves. */
23
23
  export declare const SUPPORTED_SLOTS_CONTRACT_VERSIONS: readonly number[];
24
24
  export interface SlotContent {
25
25
  slot_id: string;
@@ -63,7 +63,7 @@ export interface SlotResolveRequestEntry {
63
63
  export interface SlotsResolveRequest {
64
64
  contract_version: number;
65
65
  slots: SlotResolveRequestEntry[];
66
- /** Multi-site sub-dimension: normalized lowercase host (see CLAUDE.md "site" convention). */
66
+ /** Multi-site sub-dimension: normalized lowercase host. */
67
67
  site?: string;
68
68
  }
69
69
  export interface SlotsResolveResponse {
@@ -83,7 +83,7 @@ type Signable = Pick<SlotContent, 'slot_id' | 'type' | 'content'> & {
83
83
  */
84
84
  export declare function slotSigningPayload(content: Signable, version?: number): string;
85
85
  /**
86
- * Sign slot content with the project API key (sonor-api side).
86
+ * Sign slot content with the project API key (Sonor's side).
87
87
  * Returns the hex HMAC-SHA256 signature.
88
88
  */
89
89
  export declare function signSlotContent(content: Signable, apiKey: string, version?: number): string;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Stands in for every character that isn't prose (code, quotations, link
3
+ * destinations). It's neither whitespace nor a word character, so a masked
4
+ * span still separates words and no pattern can match it.
5
+ */
6
+ export declare const VOICE_MASK = "\u2800";
7
+ export interface VoiceHit {
8
+ /** UTF-16 offset into the whole string you passed in, never line-relative. */
9
+ readonly index: number;
10
+ /** Length of the span to replace. May include a run of spaces or tabs. */
11
+ readonly length: number;
12
+ /** The text at [index, index + length) of the string you passed in. */
13
+ readonly match: string;
14
+ /** What to put there, first-letter case preserved. Always a straight apostrophe. */
15
+ readonly suggestion: string;
16
+ }
17
+ export interface VoiceOptions {
18
+ /**
19
+ * The text is a heading or title, so one that opens with "What Is" keeps it.
20
+ * Applies to every line. Pass the heading text, not the Markdown line: `#`
21
+ * and list markers must already be blanked.
22
+ */
23
+ readonly titleLike?: boolean | undefined;
24
+ /**
25
+ * Half-open [start, end) UTF-16 ranges to leave alone, computed from the
26
+ * exact string passed in. Any order, overlaps and touching ranges allowed.
27
+ * Start is floored and clamped to 0 (so -Infinity means "from the start"),
28
+ * end is ceiled and clamped to the text length (so Infinity means "to the
29
+ * end"), and an empty or out-of-text range is ignored. Every protected
30
+ * character is masked except "\n" and "\r", which stay as they are (a
31
+ * protected line break still ends its line). A malformed range (NaN, a
32
+ * non-number, or start after end) or a truthy value that isn't an array
33
+ * protects the whole text: protection never fails open. A falsy value means
34
+ * no ranges.
35
+ */
36
+ readonly protectedRanges?: ReadonlyArray<readonly [number, number]> | undefined;
37
+ }
38
+ /**
39
+ * Full forms the house voice contracts ("do not" -> "don't"). Read one line at
40
+ * a time: split on "\n"; a "\r" right before it, or at the very end of the
41
+ * text, ends the line with it; any other "\r" is text.
42
+ * Sorted by index, never overlapping, [] for ''.
43
+ */
44
+ export declare function findUncontracted(text: string, options?: VoiceOptions): VoiceHit[];
45
+ /**
46
+ * `text` with every findUncontracted hit applied. Returns `text` itself when
47
+ * nothing applies, and for anything that isn't a string. Protected characters
48
+ * are never rewritten.
49
+ */
50
+ export declare function contractText(text: string, options?: VoiceOptions): string;
51
+ /**
52
+ * Contractions a question-form heading or FAQ question must expand
53
+ * ("What's" -> "What is"). Sorted by index, never overlapping. `titleLike` is
54
+ * not part of this direction.
55
+ */
56
+ export declare function findContracted(text: string, options?: Pick<VoiceOptions, 'protectedRanges'>): VoiceHit[];
@@ -5,14 +5,14 @@
5
5
  * SINGLE SOURCE OF TRUTH shared by every side of the Website module's popups:
6
6
  * - the site (site-kit measures its own rendered design and reports it,
7
7
  * publishes it as `--sk-site-*` CSS variables, and renders popup blocks),
8
- * - sonor-api (validates the design report and every popup write with these
8
+ * - the Sonor API (validates the design report and every popup write with these
9
9
  * normalizers, so a popup can't be saved in a shape the site can't draw),
10
10
  * - the dashboard (the builder's preview reads the same tokens through the
11
11
  * same CSS-variable mapping, so it looks like the site),
12
12
  * - Signal's agents (the block shapes an MCP `propose_site_popup` sends).
13
13
  *
14
14
  * All four import it: site-kit as `@sonordev/site-kit/website/contract`,
15
- * sonor-api and the dashboard as `@sonordev/contracts/website`.
15
+ * the API and the dashboard as `@sonordev/contracts/website`.
16
16
  *
17
17
  * Why popups carry blocks and the site carries tokens: a popup should look
18
18
  * like the site it's on. It says WHAT (a heading, some formatted text, an
@@ -1,20 +1,21 @@
1
1
  /**
2
- * @sonordev/site-kit/engage - Engage Widget
2
+ * @sonordev/site-kit/engage - EngageWidget: deprecated, kept through 7.x.
3
3
  *
4
- * Loads and renders engagement widgets (popups, nudges, bars, chat) via Portal API
5
- * Supports both legacy config-based rendering and new design_json from Engage Studio
4
+ * Engage was retired in Sonor. SiteKitLayout mounts website chat and popups
5
+ * for you (its `chat` and `popups` props). To place them yourself, use
6
+ * `SiteChat` from `@sonordev/site-kit/chat` and `SitePopups` from
7
+ * `@sonordev/site-kit/website/popups`. This draws exactly those two, so a
8
+ * site that still renders <EngageWidget /> keeps working. Removed in 8.0.
6
9
  */
7
10
  import React from 'react';
8
- import type { ChatLauncherPlacement } from './types';
9
- import { type AnalyticsGateOptions } from '../shared/reporting-gate';
10
- interface EngageWidgetProps extends ChatLauncherPlacement, AnalyticsGateOptions {
11
- apiUrl?: string;
12
- apiKey?: string;
13
- projectId?: string;
11
+ import { type SiteChatProps } from '../chat/SiteChat';
12
+ /** @deprecated Use SiteChat and SitePopups, or SiteKitLayout's `chat` and `popups`. */
13
+ export interface EngageWidgetProps extends SiteChatProps {
14
+ /** Show the chat launcher. Default true. */
14
15
  chatEnabled?: boolean;
15
- /** Load and show the site's popups, banners and toasts. Default true. */
16
+ /** Show the site's popups, banners and toasts. Default true. */
16
17
  popupsEnabled?: boolean;
17
18
  debug?: boolean;
18
19
  }
19
- export declare function EngageWidget(props: EngageWidgetProps): React.JSX.Element | null;
20
- export {};
20
+ /** @deprecated Use SiteChat and SitePopups, or SiteKitLayout's `chat` and `popups`. */
21
+ export declare function EngageWidget({ chatEnabled, popupsEnabled, debug, ...props }: EngageWidgetProps): React.JSX.Element;
@@ -1,13 +1,14 @@
1
1
  /**
2
- * @sonordev/site-kit/engage
2
+ * @sonordev/site-kit/engage — deprecated, kept through 7.x so old imports
3
+ * keep building. Removed in 8.0.
3
4
  *
4
- * Engagement widgets - popups, nudges, chat
5
- * DesignRenderer for Engage Studio components
5
+ * Engage was retired in Sonor. Website chat is `@sonordev/site-kit/chat`
6
+ * (Sonor → Messages) and popups are `@sonordev/site-kit/website/popups`
7
+ * (Sonor → Website). Nothing lives here: this re-exports them under the old
8
+ * names, and EngageWidget draws SiteChat and SitePopups.
6
9
  */
7
- export { EngageWidget } from './EngageWidget';
8
- export { ChatWidget } from './ChatWidget';
9
- export { DesignRenderer } from './DesignRenderer';
10
- export type { DesignDocument, DesignNode, ActionConfig, EngageContext } from './DesignRenderer';
10
+ export { EngageWidget, type EngageWidgetProps } from './EngageWidget';
11
+ export { ChatWidget } from '../chat/ChatWidget';
12
+ export { SONOR_PUBLIC_ECHO_DEFAULTS, getEchoWidgetProps } from '../chat/echo-config';
13
+ export type { EchoPublicConfig } from '../chat/echo-config';
11
14
  export * from './types';
12
- export { SONOR_PUBLIC_ECHO_DEFAULTS, getEchoWidgetProps } from './echo-config';
13
- export type { EchoPublicConfig } from './echo-config';
@@ -1,12 +1,16 @@
1
1
  'use client';
2
- export { ChatWidget } from '../chunk-V4HUSHZO.js';
3
- import '../chunk-JE4A5S4F.js';
4
- export { DesignRenderer, EngageWidget } from '../chunk-B73QPZPH.js';
5
- import '../chunk-NDF4A5JM.js';
2
+ export { SONOR_PUBLIC_ECHO_DEFAULTS, getEchoWidgetProps } from '../chunk-HODO5BX5.js';
3
+ export { ChatWidget } from '../chunk-64DKGVEI.js';
4
+ import { SiteChat } from '../chunk-NV72HZ4W.js';
6
5
  import '../chunk-6T6CQVNL.js';
7
- import '../chunk-NEKEH4CK.js';
8
- import '../chunk-AQSNPZY4.js';
6
+ import '../chunk-JE4A5S4F.js';
7
+ import { SitePopups } from '../chunk-EJVQJCG5.js';
8
+ import '../chunk-27FISYK4.js';
9
+ import '../chunk-FR6BYFPC.js';
10
+ import '../chunk-Q6E4OPGG.js';
11
+ import '../chunk-C2FZBUSS.js';
9
12
  import '../chunk-5SQK3D53.js';
13
+ import '../chunk-HW7B43E5.js';
10
14
  import '../chunk-NJCTQH2P.js';
11
15
  import '../chunk-S22FSH7C.js';
12
16
  import '../chunk-24QZEO3Q.js';
@@ -14,36 +18,28 @@ import '../chunk-L2V5PUFN.js';
14
18
  import '../chunk-GJWI74ZZ.js';
15
19
  import '../chunk-43OCZ3JA.js';
16
20
  import '../chunk-EKBEOXTH.js';
17
- import '../chunk-PXZ7LAOY.js';
18
- import '../chunk-OUNRFXDC.js';
19
- import '../chunk-6OL23QYD.js';
21
+ import '../chunk-D6ZC7XKZ.js';
22
+ import '../chunk-K4ZHAURD.js';
23
+ import '../chunk-F24FNCTK.js';
20
24
  import '../chunk-PKBMQBKP.js';
25
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
21
26
 
22
- // src/engage/echo-config.ts
23
- var SONOR_PUBLIC_ECHO_DEFAULTS = {
24
- signalUrl: "https://signal.sonor.io",
25
- welcomeMessage: "Hi! I'm Echo, Sonor's AI assistant. I can answer questions about our platform, help you understand pricing, or get you started with a demo. What would you like to know?",
26
- suggestedQuestions: [
27
- "What does Sonor do?",
28
- "How does Signal AI work?",
29
- "What are the pricing plans?",
30
- "Can I migrate from HubSpot?",
31
- "How does the SEO module work?"
32
- ],
33
- brandColor: "#2563eb",
34
- // blue-600 (~5.2:1 on white, AA); overridden by --sk-primary CSS var or API brand_primary
35
- assistantName: "Echo"
36
- };
37
- function getEchoWidgetProps(config = SONOR_PUBLIC_ECHO_DEFAULTS) {
38
- return {
39
- signal_enabled: true,
40
- signal_url: config.signalUrl || SONOR_PUBLIC_ECHO_DEFAULTS.signalUrl,
41
- welcome_message: config.welcomeMessage || SONOR_PUBLIC_ECHO_DEFAULTS.welcomeMessage,
42
- suggested_questions: config.suggestedQuestions || SONOR_PUBLIC_ECHO_DEFAULTS.suggestedQuestions,
43
- brand_color: config.brandColor || SONOR_PUBLIC_ECHO_DEFAULTS.brandColor,
44
- assistant_name: config.assistantName || SONOR_PUBLIC_ECHO_DEFAULTS.assistantName,
45
- assistant_avatar: config.assistantAvatar
46
- };
27
+ function EngageWidget({ chatEnabled = true, popupsEnabled = true, debug, ...props }) {
28
+ const { apiUrl, apiKey, zIndex, allowInFrame, allowLocalhost } = props;
29
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
30
+ popupsEnabled && /* @__PURE__ */ jsx(
31
+ SitePopups,
32
+ {
33
+ apiUrl,
34
+ apiKey,
35
+ zIndex,
36
+ allowInFrame,
37
+ allowLocalhost,
38
+ debug
39
+ }
40
+ ),
41
+ chatEnabled && /* @__PURE__ */ jsx(SiteChat, { ...props })
42
+ ] });
47
43
  }
48
44
 
49
- export { SONOR_PUBLIC_ECHO_DEFAULTS, getEchoWidgetProps };
45
+ export { EngageWidget };