@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
@@ -1,13 +1,13 @@
1
1
  'use client';
2
- export { SiteDesignReporter } from '../chunk-Q4W23JYM.js';
3
- export { SITE_DESIGN_PATH, cleanFontStack, colorToHex, getSiteDesignTokens, measureSiteDesign, readDeclaredDesign, sendSiteDesign } from '../chunk-PGMVL4AB.js';
4
- export { DEFAULT_POPUP_TOKENS, PopupBlocks } from '../chunk-JSZN6LDZ.js';
2
+ export { SiteDesignReporter } from '../chunk-MRQ2U4LZ.js';
3
+ export { SITE_DESIGN_PATH, cleanFontStack, colorToHex, getSiteDesignTokens, measureSiteDesign, readDeclaredDesign, sendSiteDesign } from '../chunk-I2YX3HVD.js';
4
+ export { DEFAULT_POPUP_TOKENS, PopupBlocks } from '../chunk-BF7TZYC3.js';
5
5
  import '../chunk-IHG36STL.js';
6
6
  import '../chunk-YC7ELZS3.js';
7
7
  import '../chunk-S22FSH7C.js';
8
8
  import '../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';
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @sonordev/site-kit/website/popups - the rules SitePopups applies to the
3
+ * popups, banners and toasts published for a site, as pure functions (the
4
+ * package's tests have no DOM).
5
+ */
6
+ import type { SitePopup } from './popup-types';
7
+ import type { PopupPlacement } from './PopupBlocks';
8
+ /** Exact path, or a prefix ending in `*`. The grammar Sonor stores page patterns in. */
9
+ export declare function matchPath(pathname: string, pattern: string): boolean;
10
+ export type DeviceType = 'desktop' | 'mobile' | 'tablet';
11
+ export declare function deviceFromUserAgent(ua: string): DeviceType;
12
+ /**
13
+ * The storage key that remembers a visitor saw (closed or clicked) a popup.
14
+ * The `_engage_` prefix predates the Website module; renaming it would show
15
+ * every "once" popup to visitors who already closed it.
16
+ */
17
+ export declare function seenKey(popupId: string): string;
18
+ interface SeenStore {
19
+ local: Pick<Storage, 'getItem'> | null;
20
+ session: Pick<Storage, 'getItem'> | null;
21
+ }
22
+ /** Whether a popup's targeting and frequency cap allow it on this page, for this visitor. */
23
+ export declare function isEligible(popup: SitePopup, pathname: string, device: DeviceType, store: SeenStore, now?: number): boolean;
24
+ /**
25
+ * What a popup draws as: centred over a dimmed page, a bar along an edge, or
26
+ * a slide-in (a toast) in a corner. Its `layout` says what it actually is;
27
+ * `type` describes it for older kits. Undefined for a popup without blocks:
28
+ * that's Sonor's Engage Studio `design_json`, which this kit doesn't draw.
29
+ * Single source of truth for which popups SitePopups draws, the
30
+ * one-popup-at-a-time rule and the form wait.
31
+ */
32
+ export declare function popupPlacement(popup: SitePopup): PopupPlacement | undefined;
33
+ /**
34
+ * Whether a popup waits until the visitor isn't mid-form before it opens on
35
+ * its own (shared/mid-form). Popups and toasts do. Banners don't: they
36
+ * neither take focus nor hide the page.
37
+ */
38
+ export declare function waitsForForms(popup: SitePopup): boolean;
39
+ /**
40
+ * The active list after `id` asks to show. A popup (the kind centred over a
41
+ * dimmed page) waits while another is open, so two never stack; banners and
42
+ * toasts show alongside. Popups arrive from Sonor highest priority first, so
43
+ * the first popup to trigger is the one that wins a tie.
44
+ */
45
+ export declare function activatePopup(active: string[], id: string, popups: SitePopup[]): string[];
46
+ export {};
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @sonordev/site-kit/website/popups: what a published popup looks like.
3
+ *
4
+ * Sonor → Website → Popups & Banners. The API serves them from
5
+ * `GET /engage/widget/elements` (its route keeps the retired module's name).
6
+ */
7
+ import type { PopupBlock } from './contract';
8
+ /** What Sonor says a popup is. A blocks popup's `layout` says where it actually sits. */
9
+ export type SitePopupType = 'popup' | 'nudge' | 'bar' | 'chat' | 'slide-in';
10
+ /** A popup, banner or toast published for this site (Sonor → Website → Popups & Banners). */
11
+ export interface SitePopup {
12
+ id: string;
13
+ project_id: string;
14
+ name: string;
15
+ type: SitePopupType;
16
+ config: SitePopupConfig;
17
+ targeting: SitePopupTargeting;
18
+ trigger: SitePopupTrigger;
19
+ is_active: boolean;
20
+ priority: number;
21
+ created_at: string;
22
+ updated_at: string;
23
+ /**
24
+ * The popup as blocks, drawn in the site's own design by PopupBlocks. A
25
+ * popup without blocks isn't drawn: Sonor's older `design_json` (Engage
26
+ * Studio) is for site-kits before 7.2.0, and is ignored here.
27
+ */
28
+ blocks?: PopupBlock[];
29
+ /**
30
+ * Where a blocks popup sits. `type`/`config` describe it for older kits
31
+ * (which can't pin a bar to the bottom); this says what it actually is.
32
+ */
33
+ layout?: {
34
+ placement: 'popup' | 'bar' | 'slide-in';
35
+ edge?: 'top' | 'bottom';
36
+ corner?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
37
+ /** The popup's own accent, over the site's. */
38
+ accent?: string;
39
+ };
40
+ status?: 'draft' | 'published' | 'archived' | 'paused';
41
+ }
42
+ export interface SitePopupConfig {
43
+ /** Visual style */
44
+ theme?: 'light' | 'dark' | 'custom';
45
+ position?: 'center' | 'top' | 'bottom' | 'left' | 'right' | 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
46
+ /** Content */
47
+ title?: string;
48
+ message?: string;
49
+ imageUrl?: string;
50
+ /** CTA */
51
+ ctaText?: string;
52
+ ctaUrl?: string;
53
+ ctaAction?: 'link' | 'close' | 'form' | 'chat';
54
+ /** Form (if ctaAction is 'form') */
55
+ formId?: string;
56
+ /** Styling */
57
+ backgroundColor?: string;
58
+ textColor?: string;
59
+ ctaBackgroundColor?: string;
60
+ ctaTextColor?: string;
61
+ borderRadius?: number;
62
+ /** Behavior */
63
+ closable?: boolean;
64
+ showOverlay?: boolean;
65
+ overlayOpacity?: number;
66
+ }
67
+ export interface SitePopupTargeting {
68
+ /** Page targeting */
69
+ pages?: {
70
+ include?: string[];
71
+ exclude?: string[];
72
+ };
73
+ /** Device targeting */
74
+ devices?: ('desktop' | 'mobile' | 'tablet')[];
75
+ /** Visitor targeting */
76
+ visitor?: {
77
+ type?: 'new' | 'returning' | 'all';
78
+ minSessions?: number;
79
+ maxSessions?: number;
80
+ };
81
+ /** Source targeting */
82
+ source?: {
83
+ utm_source?: string[];
84
+ utm_medium?: string[];
85
+ utm_campaign?: string[];
86
+ referrer?: string[];
87
+ };
88
+ /** Time targeting */
89
+ schedule?: {
90
+ startDate?: string;
91
+ endDate?: string;
92
+ daysOfWeek?: number[];
93
+ startTime?: string;
94
+ endTime?: string;
95
+ timezone?: string;
96
+ };
97
+ }
98
+ export interface SitePopupTrigger {
99
+ type: 'immediate' | 'delay' | 'scroll' | 'exit-intent' | 'click' | 'custom';
100
+ /** Delay in seconds (for 'delay' type) */
101
+ delay?: number;
102
+ /** Scroll percentage (for 'scroll' type) */
103
+ scrollPercentage?: number;
104
+ /** CSS selector (for 'click' type) */
105
+ clickSelector?: string;
106
+ /** Custom event name (for 'custom' type) */
107
+ customEvent?: string;
108
+ /** Frequency capping */
109
+ frequency?: {
110
+ type: 'always' | 'once' | 'once-per-session' | 'every-n-days';
111
+ days?: number;
112
+ };
113
+ }
@@ -7,11 +7,7 @@
7
7
  * import it to place it yourself. `PopupBlocks` is the renderer, for drawing
8
8
  * one popup from its blocks.
9
9
  */
10
- import React from 'react';
11
- import { EngageWidget } from '../engage/EngageWidget';
12
- export type SitePopupsProps = Omit<React.ComponentProps<typeof EngageWidget>, 'chatEnabled'>;
13
- /** The site's published popups, banners and toasts. No chat launcher (that's `./chat`). */
14
- export declare function SitePopups(props: SitePopupsProps): React.JSX.Element;
10
+ export { SitePopups, type SitePopupsProps } from './SitePopups';
15
11
  export { PopupBlocks, DEFAULT_POPUP_TOKENS, type PopupBlocksProps, type PopupPlacement } from './PopupBlocks';
16
- export type { EngageElement as SitePopup } from '../engage/types';
12
+ export type { SitePopup, SitePopupConfig, SitePopupTargeting, SitePopupTrigger, SitePopupType, } from './popup-types';
17
13
  export type { PopupBlock, SiteDesignTokens } from './contract';
@@ -1,22 +1,14 @@
1
1
  'use client';
2
- export { DEFAULT_POPUP_TOKENS, PopupBlocks } from '../chunk-JSZN6LDZ.js';
2
+ export { DEFAULT_POPUP_TOKENS, PopupBlocks } from '../chunk-BF7TZYC3.js';
3
3
  import '../chunk-IHG36STL.js';
4
- import { EngageWidget } from '../chunk-YCJT4JJG.js';
5
- import '../chunk-NDF4A5JM.js';
6
- import '../chunk-6T6CQVNL.js';
4
+ export { SitePopups } from '../chunk-YJLS6JBI.js';
5
+ import '../chunk-27FISYK4.js';
7
6
  import '../chunk-S22FSH7C.js';
8
7
  import '../chunk-24QZEO3Q.js';
9
8
  import '../chunk-GJWI74ZZ.js';
10
9
  import '../chunk-43OCZ3JA.js';
11
10
  import '../chunk-EKBEOXTH.js';
12
- import '../chunk-3SDOQUUF.js';
13
- import '../chunk-VDF5DFWT.js';
14
- import '../chunk-AH5Q262S.js';
11
+ import '../chunk-BEBR4OJD.js';
12
+ import '../chunk-WGG6GTKW.js';
13
+ import '../chunk-56KNHB4U.js';
15
14
  import '../chunk-PKBMQBKP.js';
16
- import { jsx } from 'react/jsx-runtime';
17
-
18
- function SitePopups(props) {
19
- return /* @__PURE__ */ jsx(EngageWidget, { ...props, chatEnabled: false });
20
- }
21
-
22
- export { SitePopups };
@@ -1,9 +1,9 @@
1
- export { writeLLMsTxtToPublic } from './chunk-QEDHRBAT.js';
2
- import './chunk-GLHQ3LRO.js';
1
+ export { writeLLMsTxtToPublic } from './chunk-Z65DHMTW.js';
2
+ import './chunk-6U3VLV2C.js';
3
3
  import './chunk-L5UOHS6E.js';
4
4
  import './chunk-WMVK77ND.js';
5
5
  import './chunk-VX5CMNMM.js';
6
- import './chunk-4Y5FWDPM.js';
6
+ import './chunk-NZ4RXN3G.js';
7
7
  import './chunk-MJP63SSS.js';
8
8
  import './chunk-YVKRYQRG.js';
9
9
  import './chunk-FESKKJAS.js';
@@ -20,6 +20,13 @@ idempotent: running it twice changes nothing the second time. It works from
20
20
  any 2.x-6.x site: copies of sites on 4.2, 5.8 and 6.5 were migrated with it
21
21
  and built.
22
22
 
23
+ It leaves nothing in the project but the change. Since sonor-setup 7.1.2 the
24
+ originals of the files it writes go to a folder in your OS temp directory
25
+ (it prints where, and git has them too), not `.bak` files beside them, and
26
+ it never creates or edits `.env.example`: `.env.local` is the one env file.
27
+ An old fallback such as `process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY`
28
+ becomes `process.env.SONOR_API_KEY`.
29
+
23
30
  Requirements: Next 16 and Node 20.19+ or 22.12+
24
31
  (Netlify's default is 22).
25
32
 
@@ -68,12 +75,17 @@ New homes, each the same module as before:
68
75
 
69
76
  - Website: `./website/{popups,images,slots,cms,landing,cta-bar}`
70
77
  - SEO: `./seo/{sitemap,robots,indexnow,redirects,og,og/route,llms,llms/client,llms/contract,meta/contract,pages/contract}`
71
- - Website chat: `./chat` (out of `./engage`)
78
+ - Website chat: `./chat`, and popups: `./website/popups` (both out of
79
+ `./engage`, which Sonor retired with the Engage module)
72
80
 
73
81
  **The old paths keep working through 7.x** and are removed in 8.0. The
74
- codemod moves them anyway, so a touched site is done in one pass.
75
- `SiteKitLayout` gains `chat` and `popups` props; `engage` is an alias
76
- (`engage={false}` still turns both off).
82
+ codemod moves them anyway, so a touched site is done in one pass: chat
83
+ imports go to `./chat`, popup types to `./website/popups` under their new
84
+ names (`EngageElement` is `SitePopup`). It flags `EngageWidget`, which draws
85
+ both and which `SiteKitLayout` already mounts. `SiteKitLayout` gains `chat`
86
+ and `popups` props; `engage` is an alias (`engage={false}` still turns both
87
+ off). Since 7.2.0, popups render only from blocks: one made in Engage Studio
88
+ isn't drawn, so make it again in Sonor (Website → Popups & Banners).
77
89
 
78
90
  ### 4. ESM only, Next 16 only
79
91
 
@@ -85,10 +97,22 @@ site-side script that `require()`s site-kit on an older Node would break.
85
97
  The `next` peer is `^16`. Next 16 renamed `middleware.ts` to `proxy.ts`, and
86
98
  **the codemod moves it**: the file, a named `middleware` export (to `proxy`),
87
99
  and `createMiddleware` from `@sonordev/site-kit/middleware` (to `createProxy`
88
- from `/proxy`). The old names work through 7.x. It won't move a file that
89
- sets `runtime` (a proxy file can't; the build throws), and says so: remove
90
- the export, check the logic still runs on your host, rerun. It never moves
91
- onto an existing `proxy.ts`. `npx sonor-setup next16` runs just this part.
100
+ from `/proxy`). The old names work through 7.x.
101
+
102
+ **The proxy goes beside the app directory.** Next reads it from the project
103
+ root, or from `src/` when the app is `src/app`, and silently ignores one
104
+ anywhere else: the build passes, but the site sends no security headers and
105
+ runs no managed redirects. So on a `src/app` site the codemod writes
106
+ `src/proxy.ts`, with the file's relative imports re-pointed. Before
107
+ sonor-setup 7.1.2 it renamed the file in place, which left a root `proxy.ts`
108
+ on those sites; rerunning the codemod moves it, and `npx sonor-setup doctor`
109
+ warns about any proxy Next doesn't read.
110
+
111
+ It won't move a file that sets `runtime` (a proxy file can't; the build
112
+ throws), and says so: remove the export, check the logic still runs on your
113
+ host, rerun. It never moves onto a proxy Next already runs: with one in each
114
+ place, it reports both and changes neither. `npx sonor-setup next16` runs
115
+ just this part.
92
116
 
93
117
  ### 5. Removed (nothing used them)
94
118
 
@@ -119,7 +143,7 @@ Still accepted and ignored until 8.0, because sites pass them:
119
143
  `.env.local`, `.env.production`, `.env`. It used to let `.env.local` beat
120
144
  the host.
121
145
 
122
- ## Optional, and new in 7.0
146
+ ## Optional, and new in 7.x
123
147
 
124
148
  - **Cache Components.** `cacheComponents: true` in next.config works with
125
149
  site-kit now (it failed every page through 6.x). Remove route segment
@@ -134,6 +158,14 @@ Still accepted and ignored until 8.0, because sites pass them:
134
158
  `onToolCall: reportToolCallsToSonor()` to its `createMcpHandler`.
135
159
  - **`@sonordev/contracts`** is for the APIs and the dashboard; sites keep
136
160
  importing `@sonordev/site-kit/*/contract`, which is the same code.
161
+ - **Live updates (7.1).** `npx sonor-setup scaffold` writes the route Sonor
162
+ calls when content changes, `app/api/seo-revalidate/route.ts`, and
163
+ `npx sonor-setup doctor` checks for it. A site with articles gets
164
+ `createRevalidateRoute({ publicationBasePath: '/insights' })` with its own
165
+ path, read from the app directory (a dynamic page that renders site-kit
166
+ articles, or a `[slug]` route under a folder like `/blog` or `/news`).
167
+ When more than one folder looks like the publication, it writes the
168
+ one-line route and lists them.
137
169
 
138
170
  ## Kits built on site-kit
139
171
 
package/docs.json CHANGED
@@ -38,7 +38,8 @@
38
38
  "title": "Engagement",
39
39
  "pages": [
40
40
  { "slug": "forms", "title": "Forms", "file": "src/forms/README.md" },
41
- { "slug": "chat", "title": "Website chat", "file": "src/engage/README.md" },
41
+ { "slug": "chat", "title": "Website chat", "file": "src/chat/README.md" },
42
+ { "slug": "popups", "title": "Popups and banners", "file": "src/website/README.md" },
42
43
  { "slug": "cta-bar", "title": "CTA bar", "file": "src/cta-bar/README.md" },
43
44
  { "slug": "signal", "title": "Signal (A/B)", "file": "src/signal/README.md" }
44
45
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonordev/site-kit",
3
- "version": "7.1.2",
3
+ "version": "7.3.0",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@11.5.3",
6
6
  "description": "Complete client-side integration kit for Sonor - SEO, Analytics, Engage, Forms, Blog",
@@ -461,7 +461,7 @@
461
461
  "gsap": "^3.15.0",
462
462
  "happy-dom": "^20.14.5",
463
463
  "inquirer": "^14.0.2",
464
- "next": "16.3.6",
464
+ "next": "16.3.8",
465
465
  "open": "11.0.0",
466
466
  "ora": "^9.4.1",
467
467
  "playwright": "^1.62.1",
@@ -212,7 +212,7 @@ with `analytics.site` or `NEXT_PUBLIC_SITE_URL` set to a production domain.
212
212
  `localhost`, its subdomains, `127.0.0.1`, `[::1]`, and `0.0.0.0` report nothing
213
213
  by default: page views, events, conversions, sessions, vitals, scroll and
214
214
  heatmap data, fleet heartbeats, and client-side sitemap registrations all use
215
- `resolveAnalyticsTarget`. Engage doesn't mount its widgets or chat transport.
215
+ `resolveAnalyticsTarget`. Website chat and popups don't mount at all.
216
216
  Public hosts and same-origin frames on public hosts still report normally.
217
217
 
218
218
  For intentional local reporting:
@@ -222,7 +222,7 @@ For intentional local reporting:
222
222
  ```
223
223
 
224
224
  The layout passes this option to AnalyticsProvider, WebVitals, FleetHeartbeat,
225
- SitemapSync and EngageWidget. Standalone components and `sendFleetHeartbeat`
225
+ SitemapSync, SiteChat and SitePopups. Standalone components and `sendFleetHeartbeat`
226
226
  accept it too; standalone `trackEvent`/`trackConversion` use their mounted
227
227
  AnalyticsProvider's options. A local cross-origin frame needs **both** opt-ins.
228
228
  Neither option bypasses authentication. No environment variable or global
@@ -47,7 +47,10 @@ const href = createPublicationRoutes(routing).post({ slug: 'build-first', catego
47
47
  provide `postPath: post => '/articles/' + encodeURIComponent(post.slug)`.
48
48
  Callbacks return local paths; generated metadata, feeds, and sitemaps separately
49
49
  honor a valid `canonical_url`. The same routes apply to Atom and generated
50
- breadcrumb/cluster schemas. Supplied `schema`/`schema_json` objects stay intact.
50
+ breadcrumb/cluster schemas. Supplied `schema`/`schema_json` objects stay intact, apart
51
+ from template placeholders (an `Organization` named "Example", `example.com` URLs,
52
+ `{post.title}`), which `generateAllArticleSchemas` drops. When nothing real is left,
53
+ it generates the article's schema from its own fields instead.
51
54
 
52
55
  For custom layouts, `resolveArticleArtwork(post, 'article')` prefers
53
56
  `editorial_image`, preserving an empty decorative `editorial_image_alt`.
@@ -1,58 +1,69 @@
1
- # Engage — `@sonordev/site-kit/engage`
1
+ # Website chat — `@sonordev/site-kit/chat`
2
2
 
3
- Popups, nudges, bars, slide-ins, and chat widgets — all configured from the Sonor dashboard.
3
+ Echo's chat launcher and conversation on your site, configured in Sonor
4
+ (Messages → Chat settings). AI answers, live handoff to your team, and an
5
+ offline form when nobody's around.
4
6
 
5
7
  ## Usage
6
8
 
7
- Auto-included by `SiteKitLayout`. For standalone use:
9
+ `SiteKitLayout` mounts it for you, after the page goes idle:
10
+
11
+ ```tsx
12
+ <SiteKitLayout>{children}</SiteKitLayout> // chat on (default)
13
+ <SiteKitLayout chat={{ offsetBottom: '88px' }}>{children}</SiteKitLayout>
14
+ <SiteKitLayout chat={false}>{children}</SiteKitLayout> // no chat
15
+ ```
16
+
17
+ On a site without `SiteKitLayout`, mount `SiteChat` the same way:
8
18
 
9
19
  ```tsx
10
20
  'use client'
11
- import { EngageWidget } from '@sonordev/site-kit/engage'
12
-
13
- export default function Layout({ children }) {
14
- return (
15
- <>
16
- {children}
17
- <EngageWidget />
18
- </>
19
- )
21
+ import { SiteChat } from '@sonordev/site-kit/chat'
22
+
23
+ export function Chat() {
24
+ return <SiteChat position="bottom-right" />
20
25
  }
21
26
  ```
22
27
 
28
+ `SiteChat` waits for the browser to go idle, skips cross-origin frames and
29
+ localhost (like analytics), and downloads the chat widget only when it
30
+ renders. `ChatWidget` is the widget itself, for a page that resolves those
31
+ choices on its own.
32
+
23
33
  ## Props
24
34
 
25
35
  ```ts
26
- interface EngageWidgetProps {
27
- apiUrl?: string // Default: https://api.sonor.io
28
- apiKey?: string // From SiteKitLayout or env
29
- projectId?: string // For chat routing
36
+ interface SiteChatProps {
37
+ apiUrl?: string // Default: from SiteKitLayout, else https://api.sonor.io
38
+ apiKey?: string // Default: from SiteKitLayout
39
+ projectId?: string // For chat routing. Resolved from the key when absent
30
40
  position?: 'bottom-right' | 'bottom-left' // Default: 'bottom-right'
31
41
  offsetBottom?: string | number // Default: '20px'. See "Launcher placement"
32
- zIndex?: number // Default: 9999. Popups, nudges, bars and the chat. See "Stacking"
33
- chatEnabled?: boolean // Default: true. See "The chat switch"
34
- debug?: boolean
42
+ zIndex?: number // Default: 9999. See "Stacking"
43
+ allowInFrame?: boolean // Show inside a cross-origin frame. Default: false
44
+ allowLocalhost?: boolean // Show on localhost. Default: false
35
45
  }
36
46
  ```
37
47
 
38
- Through `SiteKitLayout`, the same options go in `engage={{ ... }}`.
48
+ Through `SiteKitLayout`, the placement options go in `chat={{ ... }}`. The
49
+ deprecated `engage={{ ... }}` still works through 7.x.
39
50
 
40
51
  ## The chat switch
41
52
 
42
- Echo follows the project's **Enable Chat Widget** switch in Sonor (Engage,
43
- Chat settings). A project that has never saved chat settings counts as on, so
44
- Echo is on by default and only an owner who switches it off hides it. It also
45
- needs the project's **Engage** module on (Project Settings); without it Sonor
46
- answers off, since the chat has nowhere to take a visitor's message.
53
+ Echo follows the project's **Show the chat widget** switch in Sonor
54
+ (Messages → Chat settings). A project that has never saved chat settings
55
+ counts as on, so Echo is on by default and only an owner who switches it off
56
+ hides it. It also needs the project's **Website chat** module on (Project
57
+ Settings); without it Sonor answers off, since the chat has nowhere to take a
58
+ visitor's message.
47
59
 
48
60
  - The launcher appears once `GET /engage/widget/config` answers. Nothing
49
61
  renders before that, so a switched-off site never flashes a launcher, and
50
62
  it never starts Echo's availability polling.
51
63
  - If the config can't be fetched, the launcher stays hidden. The chat can't
52
64
  run without the API anyway.
53
- - `chatEnabled: false` (or `engage={false}`) in code still turns chat off
54
- whatever the switch says. Code can turn Echo off; it can't force it on over
55
- the owner's switch.
65
+ - `chat={false}` in code still turns chat off whatever the switch says. Code
66
+ can turn Echo off; it can't force it on over the owner's switch.
56
67
 
57
68
  ## Liquid Glass (6.1.0)
58
69
 
@@ -75,7 +86,7 @@ recipe (`src/shared/glass.tsx`), the same material as the mobile CTA bar
75
86
  panel, and otherwise pulls it toward black (light panel) or white (dark
76
87
  panel) just far enough to clear it: `#d4af37` gold becomes `#887023`. Fills
77
88
  (launcher, avatar, the visitor's bubbles, buttons) keep the raw brand. One
78
- helper decides this, `src/engage/brand-color.ts`; route any new brand
89
+ helper decides this, `src/chat/brand-color.ts`; route any new brand
79
90
  foreground through it. `--sk-primary` can be hex, `rgb()` or `hsl()`.
80
91
  - **Fields are 16px.** iOS Safari zooms the whole page into any focused field
81
92
  under 16px; the chat input and the inline Echo forms were 13.5-14px.
@@ -104,7 +115,7 @@ it without `!important`. Don't write that override; declare the offset instead.
104
115
  **A fixed offset, every page:** pass `offsetBottom`.
105
116
 
106
117
  ```tsx
107
- <SiteKitLayout engage={{ offsetBottom: '88px' }}>{children}</SiteKitLayout>
118
+ <SiteKitLayout chat={{ offsetBottom: '88px' }}>{children}</SiteKitLayout>
108
119
  ```
109
120
 
110
121
  Any CSS length works (`'5.5rem'`, `'calc(4rem + 8px)'`); a number is pixels.
@@ -148,13 +159,14 @@ popup maxHeight = 100dvh - launcher bottom - 100px
148
159
 
149
160
  ### Stacking
150
161
 
151
- `zIndex` is the one layer everything Engage renders sits on: popups, nudges,
152
- bars and the chat launcher. The chat popup sits one layer beneath the
153
- launcher. The default is 9999, above almost anything a site draws, so lower it
154
- when your own fixed UI (a mobile menu, a cookie banner) has to cover the chat:
162
+ `zIndex` is the layer the chat launcher sits on, with the chat window one
163
+ layer beneath it. Through `SiteKitLayout` the same number also stacks the
164
+ site's popups, banners and toasts. The default is 9999, above almost anything
165
+ a site draws, so lower it when your own fixed UI (a mobile menu, a cookie
166
+ banner) has to cover the chat:
155
167
 
156
168
  ```tsx
157
- <SiteKitLayout engage={{ zIndex: 40 }}>{children}</SiteKitLayout>
169
+ <SiteKitLayout chat={{ zIndex: 40 }}>{children}</SiteKitLayout>
158
170
  ```
159
171
 
160
172
  ```
@@ -162,9 +174,9 @@ launcher z-index = zIndex (default 9999)
162
174
  popup z-index = zIndex - 1
163
175
  ```
164
176
 
165
- At `zIndex` 0 or below the popup shares the launcher's layer instead, because
166
- -1 would put it behind the page's own content. The launcher still paints on
167
- top.
177
+ At `zIndex` 0 or below the chat window shares the launcher's layer instead,
178
+ because -1 would put it behind the page's own content. The launcher still
179
+ paints on top.
168
180
 
169
181
  ### Layout vs visual viewport on phones
170
182
 
@@ -194,29 +206,9 @@ It's opt-in: while a field has focus the gap grows to the keyboard's height,
194
206
  so everything that reads it rides above the keyboard. `useVisualViewportGap()`
195
207
  is the hook form for an existing client component.
196
208
 
197
- ## Element Types
198
-
199
- | Type | Description |
200
- |------|-------------|
201
- | `popup` | Modal overlay with CTA |
202
- | `nudge` | Small corner notification |
203
- | `bar` | Top/bottom sticky bar |
204
- | `slide-in` | Side panel |
205
- | `chat` | AI/live chat widget |
209
+ ## Chat config
206
210
 
207
- ## Targeting & Triggers
208
-
209
- All configured in the Sonor dashboard — no code changes needed:
210
-
211
- - **Page targeting** — include/exclude paths with wildcard support
212
- - **Device targeting** — desktop, mobile, tablet
213
- - **Visitor targeting** — new vs returning visitors
214
- - **Triggers** — immediate, delay (seconds), scroll (%), exit-intent, click, custom
215
- - **Frequency capping** — once, once-per-session, every N days
216
-
217
- ## Chat Widget
218
-
219
- Supports AI mode (Echo), live mode, and hybrid (AI + human handoff):
211
+ AI mode (Echo), live mode, and hybrid (AI with a human handoff). `ChatWidget` takes these as `config`; Sonor sends the rest from Chat settings:
220
212
 
221
213
  ```ts
222
214
  interface ChatConfig {
@@ -236,6 +228,15 @@ interface ChatConfig {
236
228
  }
237
229
  ```
238
230
 
239
- ## Tracking
231
+ ## Popups
232
+
233
+ Popups, banners and toasts are their own module now:
234
+ [Popups and banners](../website/README.md) (`@sonordev/site-kit/website/popups`).
235
+
236
+ ## `@sonordev/site-kit/engage` (deprecated)
240
237
 
241
- Impressions and clicks are automatically tracked via the Sonor API. Shares visitor ID (`_sk_vid`) with Analytics for cross-module attribution.
238
+ Engage was retired in Sonor. Its entry stays through 7.x so old imports keep
239
+ building: `ChatWidget` and the chat types re-export from here, and
240
+ `EngageWidget` draws `SiteChat` and `SitePopups`. Engage Studio's renderer
241
+ (`DesignRenderer`) is gone; popups render from blocks. Import
242
+ `@sonordev/site-kit/chat` and `@sonordev/site-kit/website/popups` instead.