@sonordev/site-kit 7.2.0 → 7.4.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 (108) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/agent-manifest.json +6 -4
  3. package/dist/{AnalyticsProvider-SLFFBRPE.js → AnalyticsProvider-BQXV3ZF3.js} +4 -4
  4. package/dist/{ArticleViewTracker-TM5AMGN2.js → ArticleViewTracker-3DH53RSB.js} +3 -3
  5. package/dist/{BlocksPopup-YJNJIVPO.js → BlocksPopup-FGWYVHCH.js} +4 -4
  6. package/dist/{ChatWidget-XKOSH66S.js → ChatWidget-CDQZCLVH.js} +5 -5
  7. package/dist/{FileField-CI4UL5SH.js → FileField-IPJ7L2W6.js} +3 -3
  8. package/dist/{FormSpotlight-F2AAEGBN.js → FormSpotlight-CQI2DBWI.js} +1 -1
  9. package/dist/{FormStage-BI5R5CNC.js → FormStage-4WHD6ED4.js} +1 -1
  10. package/dist/{ManagedForm-G6COGHXL.js → ManagedForm-7FZNH4L2.js} +6 -6
  11. package/dist/{ManagedNewsletterForm-BO3WCGXX.js → ManagedNewsletterForm-3D2BK3KQ.js} +4 -4
  12. package/dist/{SignalCore-ZA6WHKBR.js → SignalCore-HEQYITTM.js} +3 -3
  13. package/dist/{SiteChat-YJADDTKG.js → SiteChat-DMPDXY3W.js} +1 -1
  14. package/dist/{SiteDesignReporter-5YAW36AQ.js → SiteDesignReporter-Y2IOJE52.js} +5 -5
  15. package/dist/{SitePopups-ST5PMKZE.js → SitePopups-HD2LDKVU.js} +4 -4
  16. package/dist/SitemapSync-OKPZHRX6.js +8 -0
  17. package/dist/_client/booking-widget.js +5 -5
  18. package/dist/_client/testimonial-section.d.ts +1 -1
  19. package/dist/_client/testimonial-section.js +2 -1
  20. package/dist/affiliates/index.js +3 -3
  21. package/dist/analytics/index.js +4 -4
  22. package/dist/articles/index.js +1 -1
  23. package/dist/articles/server-ui.js +1 -1
  24. package/dist/chat/index.js +6 -6
  25. package/dist/{chunk-D6ZC7XKZ.js → chunk-3E3PPSNR.js} +2 -2
  26. package/dist/{chunk-6U3VLV2C.js → chunk-4BHRA7TI.js} +1 -1
  27. package/dist/{chunk-R46IQIGK.js → chunk-4DJMJ4V5.js} +2 -2
  28. package/dist/{chunk-BC4Y3S3D.js → chunk-5O62CER4.js} +7 -3
  29. package/dist/{chunk-EJVQJCG5.js → chunk-6LLTLLEJ.js} +2 -2
  30. package/dist/{chunk-BR4ZKUHH.js → chunk-7HPZSWS4.js} +17 -1
  31. package/dist/{chunk-S54ECQGY.js → chunk-AH4AXO4P.js} +1 -1
  32. package/dist/{chunk-D5DCBD4Y.js → chunk-ATE6IFVK.js} +1 -1
  33. package/dist/{chunk-GGORNBSC.js → chunk-AV4QAK5F.js} +1 -1
  34. package/dist/chunk-CAT235HY.js +13 -0
  35. package/dist/{chunk-JJ3DELUL.js → chunk-CG4ETW5Y.js} +2 -2
  36. package/dist/{chunk-JWTQS5F5.js → chunk-CKW4HFJG.js} +1 -1
  37. package/dist/{chunk-FR6BYFPC.js → chunk-CSN45MHO.js} +1 -1
  38. package/dist/{chunk-GEXT7BTE.js → chunk-D2RGEWHS.js} +1 -1
  39. package/dist/{chunk-JMLK6MH7.js → chunk-DA5XC7Y6.js} +1 -1
  40. package/dist/{chunk-CF5QNFYU.js → chunk-EHR4NIMX.js} +2 -2
  41. package/dist/{chunk-5V2V5C3Y.js → chunk-FUQTV5O6.js} +1 -1
  42. package/dist/{chunk-K4ZHAURD.js → chunk-GK7TV7EK.js} +1 -1
  43. package/dist/{chunk-RPZ7OQGD.js → chunk-IE5SSOCN.js} +3 -10
  44. package/dist/{chunk-HGFAEDG3.js → chunk-JRCNUUNG.js} +1 -1
  45. package/dist/{chunk-F24FNCTK.js → chunk-KHQ5GD6T.js} +1 -1
  46. package/dist/{chunk-IAM3D3RL.js → chunk-MDP7EB4J.js} +3 -3
  47. package/dist/{chunk-BKY2ZNM7.js → chunk-MHGAZ3LL.js} +1 -1
  48. package/dist/chunk-OD2ULW5Z.js +57 -0
  49. package/dist/{chunk-64DKGVEI.js → chunk-OOD6GMT4.js} +2 -2
  50. package/dist/{chunk-OWZ7ATLZ.js → chunk-PF64OEXC.js} +1 -1
  51. package/dist/{chunk-5YCEMV2L.js → chunk-PQDJNIHR.js} +1 -1
  52. package/dist/{chunk-VX5CMNMM.js → chunk-UAYAJPEP.js} +7 -1
  53. package/dist/{chunk-VHKEF5ZB.js → chunk-XA2BNW5M.js} +1 -1
  54. package/dist/{chunk-VO3JYRT5.js → chunk-XEMHGJEG.js} +8 -8
  55. package/dist/{chunk-NV72HZ4W.js → chunk-YCFW2OQO.js} +1 -1
  56. package/dist/{chunk-QL6XNPSD.js → chunk-ZTLU3BSW.js} +26 -9
  57. package/dist/client/index.js +3 -3
  58. package/dist/commerce/index.js +4 -4
  59. package/dist/engage/index.js +7 -7
  60. package/dist/fleet/index.js +4 -4
  61. package/dist/forms/index.js +7 -7
  62. package/dist/forms/server.js +2 -2
  63. package/dist/images/index.js +4 -4
  64. package/dist/index.js +1 -1
  65. package/dist/layout/client.js +7 -7
  66. package/dist/layout/index.js +9 -9
  67. package/dist/llms/agent-access.d.ts +4 -0
  68. package/dist/llms/index.js +6 -6
  69. package/dist/maps/index.js +3 -3
  70. package/dist/mcp/WebMcpTools.d.ts +5 -4
  71. package/dist/mcp/client.js +14 -7
  72. package/dist/mcp/discovery.d.ts +48 -0
  73. package/dist/mcp/handlers.d.ts +13 -7
  74. package/dist/mcp/index.d.ts +5 -3
  75. package/dist/mcp/index.js +61 -17
  76. package/dist/mcp/serverCard.d.ts +6 -7
  77. package/dist/mcp/sonor.js +8 -8
  78. package/dist/reputation/TestimonialSection.d.ts +1 -1
  79. package/dist/reputation/VisualReviewCard.d.ts +6 -0
  80. package/dist/reputation/index.d.ts +2 -1
  81. package/dist/reputation/index.js +3 -1
  82. package/dist/reputation/review-photo.d.ts +2 -0
  83. package/dist/reputation/server.d.ts +3 -2
  84. package/dist/reputation/server.js +2 -0
  85. package/dist/reputation/types.d.ts +22 -0
  86. package/dist/revalidate/index.js +2 -2
  87. package/dist/seo/client.js +4 -4
  88. package/dist/seo/index.js +4 -4
  89. package/dist/seo/llms.js +6 -6
  90. package/dist/seo/register-sitemap-cli.js +1 -1
  91. package/dist/seo/sitemap.js +4 -4
  92. package/dist/server/index.js +3 -3
  93. package/dist/server/mint-site-token.d.ts +1 -2
  94. package/dist/shared/fresh-fetch.d.ts +9 -3
  95. package/dist/shared/version.d.ts +1 -1
  96. package/dist/signal/index.js +2 -2
  97. package/dist/sitemap/index.js +4 -4
  98. package/dist/sync/index.js +5 -5
  99. package/dist/website/images.js +4 -4
  100. package/dist/website/index.js +5 -5
  101. package/dist/website/popups.js +4 -4
  102. package/dist/{writeLLMsTxt-OV24LQVL.js → writeLLMsTxt-OL4KQERZ.js} +3 -3
  103. package/package.json +1 -1
  104. package/src/forms/README.md +2 -2
  105. package/src/llms/README.md +69 -0
  106. package/src/mcp/README.md +50 -16
  107. package/src/reputation/README.md +25 -0
  108. package/dist/SitemapSync-RJTEBINX.js +0 -8
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @sonordev/site-kit Changelog
2
2
 
3
+ ## 7.4.0
4
+
5
+ - Reviews can include a project-managed photo, caption, and alternative text. Text-only reviews remain visible while imagery is pending for Broadcast.
6
+ - `VisualReviewCard` and `VisualReviewGallery` are available from the server-safe reputation entry point. `TestimonialSection` also displays attached review photos.
7
+ - Token minting supports a cold Next.js Cache Components prerender, including the default 404 page. Each mint stays fresh across deploys and token expiry, without changing form initialization or putting a raw API key into successful token responses.
8
+
9
+ ## 7.3.0
10
+
11
+ AI assistants can discover a site's existing MCP tools through more of the surfaces they read.
12
+
13
+ - **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.
14
+ - **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.
15
+ - **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.
16
+ - **Companion CLI:** sonor-setup 7.2.0 generates the catalog and canonical card routes while preserving custom-server implementations and compatibility aliases.
17
+
3
18
  ## 7.2.0
4
19
 
5
20
  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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@sonordev/site-kit",
4
- "version": "7.2.0",
4
+ "version": "7.4.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",
@@ -294,12 +294,14 @@
294
294
  {
295
295
  "name": "mcp",
296
296
  "import": "@sonordev/site-kit/mcp",
297
- "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."
298
299
  },
299
300
  {
300
301
  "name": "mcp/client",
301
302
  "import": "@sonordev/site-kit/mcp/client",
302
- "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."
303
305
  },
304
306
  {
305
307
  "name": "mcp/transport",
@@ -1,11 +1,11 @@
1
- export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-JWTQS5F5.js';
1
+ export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-CKW4HFJG.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-D6ZC7XKZ.js';
9
- import './chunk-K4ZHAURD.js';
10
- import './chunk-F24FNCTK.js';
8
+ import './chunk-3E3PPSNR.js';
9
+ import './chunk-GK7TV7EK.js';
10
+ import './chunk-KHQ5GD6T.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-D6ZC7XKZ.js';
7
- import './chunk-K4ZHAURD.js';
8
- import './chunk-F24FNCTK.js';
6
+ import { sonorFetch } from './chunk-3E3PPSNR.js';
7
+ import './chunk-GK7TV7EK.js';
8
+ import './chunk-KHQ5GD6T.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-JJ3DELUL.js';
2
+ import { getSiteDesignTokens } from './chunk-CG4ETW5Y.js';
3
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-D6ZC7XKZ.js';
9
- import './chunk-K4ZHAURD.js';
10
- import './chunk-F24FNCTK.js';
8
+ import './chunk-3E3PPSNR.js';
9
+ import './chunk-GK7TV7EK.js';
10
+ import './chunk-KHQ5GD6T.js';
11
11
  import './chunk-PKBMQBKP.js';
12
12
  import { useState } from 'react';
13
13
  import { jsx } from 'react/jsx-runtime';
@@ -1,8 +1,8 @@
1
- export { ChatWidget, EchoChat, isChatEnabled } from './chunk-64DKGVEI.js';
1
+ export { ChatWidget, EchoChat, isChatEnabled } from './chunk-OOD6GMT4.js';
2
2
  import './chunk-6T6CQVNL.js';
3
3
  import './chunk-JE4A5S4F.js';
4
4
  import './chunk-27FISYK4.js';
5
- import './chunk-FR6BYFPC.js';
5
+ import './chunk-CSN45MHO.js';
6
6
  import './chunk-Q6E4OPGG.js';
7
7
  import './chunk-C2FZBUSS.js';
8
8
  import './chunk-5SQK3D53.js';
@@ -11,7 +11,7 @@ import './chunk-NJCTQH2P.js';
11
11
  import './chunk-S22FSH7C.js';
12
12
  import './chunk-L2V5PUFN.js';
13
13
  import './chunk-GJWI74ZZ.js';
14
- import './chunk-D6ZC7XKZ.js';
15
- import './chunk-K4ZHAURD.js';
16
- import './chunk-F24FNCTK.js';
14
+ import './chunk-3E3PPSNR.js';
15
+ import './chunk-GK7TV7EK.js';
16
+ import './chunk-KHQ5GD6T.js';
17
17
  import './chunk-PKBMQBKP.js';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
- import { sonorFetch } from './chunk-D6ZC7XKZ.js';
3
- import './chunk-K4ZHAURD.js';
4
- import './chunk-F24FNCTK.js';
2
+ import { sonorFetch } from './chunk-3E3PPSNR.js';
3
+ import './chunk-GK7TV7EK.js';
4
+ import './chunk-KHQ5GD6T.js';
5
5
  import './chunk-PKBMQBKP.js';
6
6
  import React from 'react';
7
7
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { StageStyles, SummaryTick } from './chunk-J4FSB4OG.js';
3
- import { stageFirstName, useFieldControls, stageViews, stageEstimate, AUTO_ADVANCE_TYPES } from './chunk-D5DCBD4Y.js';
3
+ import { stageFirstName, useFieldControls, stageViews, stageEstimate, AUTO_ADVANCE_TYPES } from './chunk-ATE6IFVK.js';
4
4
  import { FormField } from './chunk-4NTBQNHA.js';
5
5
  import { readAgentSubmit, formToolAttributes } from './chunk-Q6E4OPGG.js';
6
6
  import { isEmptyValue, unseenControlValues, isDisplayOnly } from './chunk-C2FZBUSS.js';
@@ -1,6 +1,6 @@
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-D5DCBD4Y.js';
3
+ import { useFieldControls, stageViews, stageFirstName, stageEstimate, formatAnswer, AUTO_ADVANCE_TYPES } from './chunk-ATE6IFVK.js';
4
4
  import { FormField } from './chunk-4NTBQNHA.js';
5
5
  import { readAgentSubmit, formToolAttributes } from './chunk-Q6E4OPGG.js';
6
6
  import { isEmptyValue, unseenControlValues } from './chunk-C2FZBUSS.js';
@@ -1,8 +1,8 @@
1
- export { ManagedForm } from './chunk-IAM3D3RL.js';
2
- import './chunk-D5DCBD4Y.js';
1
+ export { ManagedForm } from './chunk-MDP7EB4J.js';
2
+ import './chunk-ATE6IFVK.js';
3
3
  import './chunk-DXO6SBMD.js';
4
4
  import './chunk-4NTBQNHA.js';
5
- import './chunk-FR6BYFPC.js';
5
+ import './chunk-CSN45MHO.js';
6
6
  import './chunk-Q6E4OPGG.js';
7
7
  import './chunk-C2FZBUSS.js';
8
8
  import './chunk-5SQK3D53.js';
@@ -10,7 +10,7 @@ import './chunk-HW7B43E5.js';
10
10
  import './chunk-NJCTQH2P.js';
11
11
  import './chunk-L2V5PUFN.js';
12
12
  import './chunk-GJWI74ZZ.js';
13
- import './chunk-D6ZC7XKZ.js';
14
- import './chunk-K4ZHAURD.js';
15
- import './chunk-F24FNCTK.js';
13
+ import './chunk-3E3PPSNR.js';
14
+ import './chunk-GK7TV7EK.js';
15
+ import './chunk-KHQ5GD6T.js';
16
16
  import './chunk-PKBMQBKP.js';
@@ -1,6 +1,6 @@
1
1
  import { NewsletterShell } from './chunk-SC4MZGWZ.js';
2
2
  import './chunk-GYF2ULVO.js';
3
- import { useForm } from './chunk-FR6BYFPC.js';
3
+ import { useForm } from './chunk-CSN45MHO.js';
4
4
  import './chunk-Q6E4OPGG.js';
5
5
  import './chunk-C2FZBUSS.js';
6
6
  import './chunk-5SQK3D53.js';
@@ -8,9 +8,9 @@ import './chunk-HW7B43E5.js';
8
8
  import './chunk-NJCTQH2P.js';
9
9
  import './chunk-L2V5PUFN.js';
10
10
  import './chunk-GJWI74ZZ.js';
11
- import './chunk-D6ZC7XKZ.js';
12
- import './chunk-K4ZHAURD.js';
13
- import './chunk-F24FNCTK.js';
11
+ import './chunk-3E3PPSNR.js';
12
+ import './chunk-GK7TV7EK.js';
13
+ import './chunk-KHQ5GD6T.js';
14
14
  import './chunk-PKBMQBKP.js';
15
15
  import { jsx } from 'react/jsx-runtime';
16
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-D6ZC7XKZ.js';
6
- import { getFreshCredential, isSiteToken } from './chunk-K4ZHAURD.js';
7
- import './chunk-F24FNCTK.js';
5
+ import { sonorFetch } from './chunk-3E3PPSNR.js';
6
+ import { getFreshCredential, isSiteToken } from './chunk-GK7TV7EK.js';
7
+ import './chunk-KHQ5GD6T.js';
8
8
  import './chunk-PKBMQBKP.js';
9
9
  import { useState, useRef, useEffect, useCallback } from 'react';
10
10
 
@@ -1,4 +1,4 @@
1
- export { SiteChat } from './chunk-NV72HZ4W.js';
1
+ export { SiteChat } from './chunk-YCFW2OQO.js';
2
2
  import './chunk-27FISYK4.js';
3
3
  import './chunk-43OCZ3JA.js';
4
4
  import './chunk-EKBEOXTH.js';
@@ -1,11 +1,11 @@
1
- export { SiteDesignReporter } from './chunk-5YCEMV2L.js';
2
- import './chunk-JJ3DELUL.js';
1
+ export { SiteDesignReporter } from './chunk-PQDJNIHR.js';
2
+ import './chunk-CG4ETW5Y.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-D6ZC7XKZ.js';
9
- import './chunk-K4ZHAURD.js';
10
- import './chunk-F24FNCTK.js';
8
+ import './chunk-3E3PPSNR.js';
9
+ import './chunk-GK7TV7EK.js';
10
+ import './chunk-KHQ5GD6T.js';
11
11
  import './chunk-PKBMQBKP.js';
@@ -1,10 +1,10 @@
1
- export { SitePopups } from './chunk-EJVQJCG5.js';
1
+ export { SitePopups } from './chunk-6LLTLLEJ.js';
2
2
  import './chunk-27FISYK4.js';
3
3
  import './chunk-24QZEO3Q.js';
4
4
  import './chunk-GJWI74ZZ.js';
5
5
  import './chunk-43OCZ3JA.js';
6
6
  import './chunk-EKBEOXTH.js';
7
- import './chunk-D6ZC7XKZ.js';
8
- import './chunk-K4ZHAURD.js';
9
- import './chunk-F24FNCTK.js';
7
+ import './chunk-3E3PPSNR.js';
8
+ import './chunk-GK7TV7EK.js';
9
+ import './chunk-KHQ5GD6T.js';
10
10
  import './chunk-PKBMQBKP.js';
@@ -0,0 +1,8 @@
1
+ export { SitemapSync } from './chunk-D2RGEWHS.js';
2
+ import './chunk-YVKRYQRG.js';
3
+ import './chunk-43OCZ3JA.js';
4
+ import './chunk-EKBEOXTH.js';
5
+ import './chunk-3E3PPSNR.js';
6
+ import './chunk-GK7TV7EK.js';
7
+ import './chunk-KHQ5GD6T.js';
8
+ import './chunk-PKBMQBKP.js';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
- export { BookingWidget, BookingWidget_default as default } from '../chunk-GGORNBSC.js';
3
- import '../chunk-BKY2ZNM7.js';
4
- import '../chunk-D6ZC7XKZ.js';
5
- import '../chunk-K4ZHAURD.js';
6
- import '../chunk-F24FNCTK.js';
2
+ export { BookingWidget, BookingWidget_default as default } from '../chunk-AV4QAK5F.js';
3
+ import '../chunk-MHGAZ3LL.js';
4
+ import '../chunk-3E3PPSNR.js';
5
+ import '../chunk-GK7TV7EK.js';
6
+ import '../chunk-KHQ5GD6T.js';
7
7
  import '../chunk-PKBMQBKP.js';
@@ -8,4 +8,4 @@
8
8
  */
9
9
  import React from 'react';
10
10
  import type { TestimonialSectionProps } from '../reputation/types';
11
- export declare function TestimonialSection({ title, subtitle, autoplay, autoplayInterval, showRating, maxReviews, featuredOnly, service, className, }: TestimonialSectionProps): React.JSX.Element | null;
11
+ export declare function TestimonialSection({ title, subtitle, autoplay, autoplayInterval, showRating, showPhoto, maxReviews, featuredOnly, service, className, }: TestimonialSectionProps): React.JSX.Element | null;
@@ -1,5 +1,6 @@
1
1
  'use client';
2
- export { TestimonialSection } from '../chunk-BR4ZKUHH.js';
2
+ export { TestimonialSection } from '../chunk-7HPZSWS4.js';
3
+ import '../chunk-CAT235HY.js';
3
4
  import '../chunk-EDYHROQ7.js';
4
5
  import '../chunk-MH2DSGC6.js';
5
6
  import '../chunk-PKBMQBKP.js';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
- import { sonorFetch } from '../chunk-D6ZC7XKZ.js';
3
- import '../chunk-K4ZHAURD.js';
4
- import '../chunk-F24FNCTK.js';
2
+ import { sonorFetch } from '../chunk-3E3PPSNR.js';
3
+ import '../chunk-GK7TV7EK.js';
4
+ import '../chunk-KHQ5GD6T.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-JWTQS5F5.js';
3
+ export { AnalyticsProvider, WebVitals, useAnalytics, useAnalyticsOptional, useTrackEvent } from '../chunk-CKW4HFJG.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-D6ZC7XKZ.js';
11
- import '../chunk-K4ZHAURD.js';
12
- import '../chunk-F24FNCTK.js';
10
+ import '../chunk-3E3PPSNR.js';
11
+ import '../chunk-GK7TV7EK.js';
12
+ import '../chunk-KHQ5GD6T.js';
13
13
  import '../chunk-PKBMQBKP.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-BO3WCGXX.js'));
18
+ var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-3D2BK3KQ.js'));
19
19
  function NewsletterWidget({
20
20
  title = "Subscribe to Our Newsletter",
21
21
  description = "Get the latest posts delivered straight to your inbox.",
@@ -133,7 +133,7 @@ async function Article({
133
133
  ...item,
134
134
  answer: addExternalLinkTargets(item.answer || "", siteUrlResolved)
135
135
  })) ?? faqRaw;
136
- const { ArticleViewTracker } = await import('../ArticleViewTracker-TM5AMGN2.js');
136
+ const { ArticleViewTracker } = await import('../ArticleViewTracker-3DH53RSB.js');
137
137
  if (children) {
138
138
  return /* @__PURE__ */ jsxs(Fragment, { children: [
139
139
  /* @__PURE__ */ jsx(ArticleViewTracker, { slug: post.slug, site }),
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
  export { SONOR_PUBLIC_ECHO_DEFAULTS, getEchoWidgetProps } from '../chunk-HODO5BX5.js';
3
- export { ChatWidget, DEFAULT_LAUNCHER_OFFSET_BOTTOM, EchoChat, chatLauncherStyles, isChatEnabled } from '../chunk-64DKGVEI.js';
4
- export { SiteChat } from '../chunk-NV72HZ4W.js';
3
+ export { ChatWidget, DEFAULT_LAUNCHER_OFFSET_BOTTOM, EchoChat, chatLauncherStyles, isChatEnabled } from '../chunk-OOD6GMT4.js';
4
+ export { SiteChat } from '../chunk-YCFW2OQO.js';
5
5
  import '../chunk-6T6CQVNL.js';
6
6
  import '../chunk-JE4A5S4F.js';
7
7
  import '../chunk-27FISYK4.js';
8
- import '../chunk-FR6BYFPC.js';
8
+ import '../chunk-CSN45MHO.js';
9
9
  import '../chunk-Q6E4OPGG.js';
10
10
  import '../chunk-C2FZBUSS.js';
11
11
  import '../chunk-5SQK3D53.js';
@@ -16,7 +16,7 @@ import '../chunk-L2V5PUFN.js';
16
16
  import '../chunk-GJWI74ZZ.js';
17
17
  import '../chunk-43OCZ3JA.js';
18
18
  import '../chunk-EKBEOXTH.js';
19
- import '../chunk-D6ZC7XKZ.js';
20
- import '../chunk-K4ZHAURD.js';
21
- import '../chunk-F24FNCTK.js';
19
+ import '../chunk-3E3PPSNR.js';
20
+ import '../chunk-GK7TV7EK.js';
21
+ import '../chunk-KHQ5GD6T.js';
22
22
  import '../chunk-PKBMQBKP.js';
@@ -1,5 +1,5 @@
1
- import { isTokenMode, getFreshCredential, isSiteToken, refreshSiteToken, currentCredential, credentialBreakerId } from './chunk-K4ZHAURD.js';
2
- import { SITE_KIT_VERSION } from './chunk-F24FNCTK.js';
1
+ import { isTokenMode, getFreshCredential, isSiteToken, refreshSiteToken, currentCredential, credentialBreakerId } from './chunk-GK7TV7EK.js';
2
+ import { SITE_KIT_VERSION } from './chunk-KHQ5GD6T.js';
3
3
 
4
4
  // src/shared/fetchWithRetry.ts
5
5
  function backoffDelay(attempt, response) {
@@ -1,4 +1,4 @@
1
- import { freshFetch } from './chunk-VX5CMNMM.js';
1
+ import { freshFetch } from './chunk-UAYAJPEP.js';
2
2
  import { LLM_GEO_CONTRACT_VERSION } from './chunk-NZ4RXN3G.js';
3
3
  import { withSiteParam } from './chunk-MJP63SSS.js';
4
4
  import { cache } from 'react';
@@ -1,6 +1,6 @@
1
1
  import { getSiteConfig } from './chunk-Z22QVHT4.js';
2
- import { writeLLMsTxtToPublic } from './chunk-QL6XNPSD.js';
3
- import { buildFetch } from './chunk-VX5CMNMM.js';
2
+ import { writeLLMsTxtToPublic } from './chunk-ZTLU3BSW.js';
3
+ import { buildFetch } from './chunk-UAYAJPEP.js';
4
4
  import { findAppDirForDiscovery } from './chunk-ZEGVKVD5.js';
5
5
  import { stripEmbeddedDomain, locToPath, inferPageType, isMalformedSitemapPath, resolveTrailingSlash, stripTrailingSlash, llmsWriteTimeoutMs, applyTrailingSlash } from './chunk-YVKRYQRG.js';
6
6
  import { postRegisterSitemap } from './chunk-DIKNRN34.js';
@@ -1,8 +1,12 @@
1
- import { generateLLMsTxt, generateLLMsFullTxt } from './chunk-QL6XNPSD.js';
1
+ import { generateLLMsTxt, generateLLMsFullTxt, appendAgentAccessSection } from './chunk-ZTLU3BSW.js';
2
2
  import { createHash } from 'crypto';
3
3
  import { existsSync, readFileSync } from 'fs';
4
4
  import { join } from 'path';
5
5
 
6
+ function withAgentAccess(markdown, options) {
7
+ const baseUrl = options.baseUrl || process.env.NEXT_PUBLIC_SITE_URL || process.env.SITE_URL || "";
8
+ return options.mcp ? appendAgentAccessSection(markdown, baseUrl, options.mcp === true ? {} : options.mcp) : markdown;
9
+ }
6
10
  function weakEtag(body) {
7
11
  const h = createHash("sha1").update(body, "utf8").digest("base64url");
8
12
  return `W/"${h}"`;
@@ -25,7 +29,7 @@ function createLLMsTxtHandler(options = {}) {
25
29
  if (preferStatic) {
26
30
  const staticPath = join(process.cwd(), "public", "llms.txt");
27
31
  if (existsSync(staticPath)) {
28
- const markdown2 = readFileSync(staticPath, "utf-8");
32
+ const markdown2 = withAgentAccess(readFileSync(staticPath, "utf-8"), generateOptions);
29
33
  return new Response(markdown2, {
30
34
  status: 200,
31
35
  headers: llmsResponseHeaders(markdown2, { ...robots, "X-Sections": "static" })
@@ -61,7 +65,7 @@ function createLLMsFullTxtHandler(options = {}) {
61
65
  if (preferStatic) {
62
66
  const staticPath = join(process.cwd(), "public", "llms-full.txt");
63
67
  if (existsSync(staticPath)) {
64
- const markdown2 = readFileSync(staticPath, "utf-8");
68
+ const markdown2 = withAgentAccess(readFileSync(staticPath, "utf-8"), generateOptions);
65
69
  return new Response(markdown2, {
66
70
  status: 200,
67
71
  headers: llmsResponseHeaders(markdown2, { ...robots, "X-Sections": "static" })
@@ -2,7 +2,7 @@
2
2
  import { DEFAULT_WIDGET_Z_INDEX } from './chunk-27FISYK4.js';
3
3
  import { getOrCreateVisitorId } from './chunk-24QZEO3Q.js';
4
4
  import { resolveAnalyticsTarget } from './chunk-43OCZ3JA.js';
5
- import { sonorFetch } from './chunk-D6ZC7XKZ.js';
5
+ import { sonorFetch } from './chunk-3E3PPSNR.js';
6
6
  import { useState, useEffect, useCallback, useRef } from 'react';
7
7
  import ReactDOM from 'react-dom';
8
8
  import dynamic from 'next/dynamic';
@@ -160,7 +160,7 @@ function activatePopup(active, id, popups) {
160
160
  return [...active, id];
161
161
  }
162
162
  var LazyBlocksPopup = dynamic(
163
- () => import('./BlocksPopup-YJNJIVPO.js').then((m) => ({ default: m.BlocksPopup })),
163
+ () => import('./BlocksPopup-FGWYVHCH.js').then((m) => ({ default: m.BlocksPopup })),
164
164
  { ssr: false }
165
165
  );
166
166
  function SitePopups(props) {
@@ -1,4 +1,5 @@
1
1
  'use client';
2
+ import { reviewPhotoUrl } from './chunk-CAT235HY.js';
2
3
  import { fetchReviews } from './chunk-EDYHROQ7.js';
3
4
  import { useState, useEffect, useCallback } from 'react';
4
5
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -9,6 +10,7 @@ function TestimonialSection({
9
10
  autoplay = true,
10
11
  autoplayInterval = 5e3,
11
12
  showRating = true,
13
+ showPhoto = true,
12
14
  maxReviews,
13
15
  featuredOnly = false,
14
16
  service,
@@ -19,6 +21,7 @@ function TestimonialSection({
19
21
  const [isLoading, setIsLoading] = useState(true);
20
22
  const [direction, setDirection] = useState("next");
21
23
  useEffect(() => {
24
+ let active = true;
22
25
  async function loadReviews() {
23
26
  setIsLoading(true);
24
27
  const data = await fetchReviews({
@@ -26,10 +29,15 @@ function TestimonialSection({
26
29
  limit: maxReviews,
27
30
  featured: featuredOnly
28
31
  });
32
+ if (!active) return;
29
33
  setReviews(data);
34
+ setCurrentIndex(0);
30
35
  setIsLoading(false);
31
36
  }
32
37
  loadReviews();
38
+ return () => {
39
+ active = false;
40
+ };
33
41
  }, [service, maxReviews, featuredOnly]);
34
42
  useEffect(() => {
35
43
  if (!autoplay || reviews.length <= 1) return;
@@ -58,6 +66,7 @@ function TestimonialSection({
58
66
  return null;
59
67
  }
60
68
  const currentReview = reviews[currentIndex];
69
+ const photoUrl = showPhoto ? reviewPhotoUrl(currentReview.photo?.url) : void 0;
61
70
  return /* @__PURE__ */ jsxs("section", { className: `testimonial-section ${className}`, "data-site-kit-testimonials": true, children: [
62
71
  /* @__PURE__ */ jsx("style", { children: `
63
72
  .testimonial-section {
@@ -69,6 +78,9 @@ function TestimonialSection({
69
78
  position: relative;
70
79
  overflow: hidden;
71
80
  }
81
+ .sk-testimonial-photo { margin:0 auto 1.5rem;max-width:42rem;overflow:hidden;border-radius:var(--sk-radius-lg,.75rem);background:var(--sk-surface); }
82
+ .sk-testimonial-photo img { display:block;width:100%;aspect-ratio:4/3;object-fit:cover; }
83
+ .sk-testimonial-photo figcaption { padding:.75rem 1rem;color:var(--sk-text-secondary);font-size:.875rem;line-height:1.5;overflow-wrap:anywhere; }
72
84
 
73
85
  .testimonial-slide {
74
86
  animation: ${direction === "next" ? "slideInRight" : "slideInLeft"} 0.6s cubic-bezier(0.4, 0, 0.2, 1);
@@ -175,8 +187,12 @@ function TestimonialSection({
175
187
  title && /* @__PURE__ */ jsx("h2", { className: "testimonial-title", children: title }),
176
188
  subtitle && /* @__PURE__ */ jsx("p", { className: "testimonial-subtitle", children: subtitle }),
177
189
  /* @__PURE__ */ jsx("div", { className: "testimonial-content", children: /* @__PURE__ */ jsxs("div", { className: "testimonial-slide", children: [
190
+ photoUrl && /* @__PURE__ */ jsxs("figure", { className: "sk-testimonial-photo", children: [
191
+ /* @__PURE__ */ jsx("img", { src: photoUrl, alt: currentReview.photo?.altText || `Photo accompanying ${currentReview.name}'s review`, loading: "lazy", decoding: "async" }),
192
+ currentReview.photo?.caption && /* @__PURE__ */ jsx("figcaption", { children: currentReview.photo.caption })
193
+ ] }),
178
194
  /* @__PURE__ */ jsx("div", { className: "testimonial-quote-icon", children: "\u201C" }),
179
- showRating && /* @__PURE__ */ jsx("div", { className: "testimonial-stars", children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsx(
195
+ showRating && /* @__PURE__ */ jsx("div", { className: "testimonial-stars", role: "img", "aria-label": `${currentReview.rating} out of 5 stars`, children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsx(
180
196
  "span",
181
197
  {
182
198
  className: `star ${i < currentReview.rating ? "star-filled" : "star-empty"}`,
@@ -54,7 +54,7 @@ function useSignal() {
54
54
  return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
55
55
  }
56
56
  var LazySignalCore = dynamic(
57
- () => import('./SignalCore-ZA6WHKBR.js').then((m) => ({ default: m.SignalCore })),
57
+ () => import('./SignalCore-HEQYITTM.js').then((m) => ({ default: m.SignalCore })),
58
58
  { ssr: false }
59
59
  );
60
60
  function SignalBridge({
@@ -26,7 +26,7 @@ function useFieldControls(fields) {
26
26
  }
27
27
  if (needsFile && !requested.current.file) {
28
28
  requested.current.file = true;
29
- import('./FileField-CI4UL5SH.js').then((m) => {
29
+ import('./FileField-IPJ7L2W6.js').then((m) => {
30
30
  if (!cancelled) setControls((prev) => ({ ...prev, File: m.FileField }));
31
31
  }).catch(() => {
32
32
  requested.current.file = false;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { detectTimezone, releaseSlotHold, fetchBookingTypeDetails, fetchBookingTypes, fetchAvailability, createSlotHold, createBooking, formatDuration, formatDate, formatTime, prepareMeeting } from './chunk-BKY2ZNM7.js';
2
+ import { detectTimezone, releaseSlotHold, fetchBookingTypeDetails, fetchBookingTypes, fetchAvailability, createSlotHold, createBooking, formatDuration, formatDate, formatTime, prepareMeeting } from './chunk-MHGAZ3LL.js';
3
3
  import { useState, useRef, useMemo, useCallback, useEffect, useId } from 'react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
 
@@ -0,0 +1,13 @@
1
+ // src/reputation/review-photo.ts
2
+ function reviewPhotoUrl(value) {
3
+ if (typeof value !== "string" || value.length > 2048) return void 0;
4
+ try {
5
+ const url = new URL(value);
6
+ if (url.protocol !== "https:" || url.username || url.password) return void 0;
7
+ return url.href;
8
+ } catch {
9
+ return void 0;
10
+ }
11
+ }
12
+
13
+ export { reviewPhotoUrl };
@@ -1,8 +1,8 @@
1
1
  import { toHexColor, normalizeDesignTokens, designTokensHash } from './chunk-IHG36STL.js';
2
2
  import { contrastRatio, parseColor, relativeLuminance } from './chunk-S22FSH7C.js';
3
3
  import { resolveAnalyticsTarget } from './chunk-43OCZ3JA.js';
4
- import { sonorFetch } from './chunk-D6ZC7XKZ.js';
5
- import { SITE_KIT_VERSION } from './chunk-F24FNCTK.js';
4
+ import { sonorFetch } from './chunk-3E3PPSNR.js';
5
+ import { SITE_KIT_VERSION } from './chunk-KHQ5GD6T.js';
6
6
 
7
7
  // src/website/design.ts
8
8
  var SITE_DESIGN_PATH = "/api/public/site/design";
@@ -3,7 +3,7 @@ import { registerAnalyticsDispatcher } from './chunk-LCDVPAMR.js';
3
3
  import { getOrCreateVisitorId, getOrCreateSessionId } from './chunk-24QZEO3Q.js';
4
4
  import { onPageLeave } from './chunk-L2V5PUFN.js';
5
5
  import { resolveAnalyticsTarget } from './chunk-43OCZ3JA.js';
6
- import { sonorFetch, sonorBeacon } from './chunk-D6ZC7XKZ.js';
6
+ import { sonorFetch, sonorBeacon } from './chunk-3E3PPSNR.js';
7
7
  import { createContext, useRef, useEffect, useState, useMemo, useCallback, useContext } from 'react';
8
8
  import { usePathname } from 'next/navigation';
9
9
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -5,7 +5,7 @@ import { normalizeFormConfig, DEFAULT_FORM_SUCCESS_MESSAGE } from './chunk-5SQK3
5
5
  import { DEFAULT_HONEYPOT_FIELD } from './chunk-NJCTQH2P.js';
6
6
  import { onPageLeave } from './chunk-L2V5PUFN.js';
7
7
  import { uuid } from './chunk-GJWI74ZZ.js';
8
- import { sonorFetch, sonorBeacon } from './chunk-D6ZC7XKZ.js';
8
+ import { sonorFetch, sonorBeacon } from './chunk-3E3PPSNR.js';
9
9
  import { useRef, useCallback, useEffect, useState, useMemo } from 'react';
10
10
 
11
11
  // src/forms/field-interactions.ts
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { locToPath, isMalformedSitemapPath, inferPageType } from './chunk-YVKRYQRG.js';
3
3
  import { resolveAnalyticsTarget } from './chunk-43OCZ3JA.js';
4
- import { sonorFetch } from './chunk-D6ZC7XKZ.js';
4
+ import { sonorFetch } from './chunk-3E3PPSNR.js';
5
5
  import { useRef, useEffect } from 'react';
6
6
 
7
7
  var SYNC_STAMP_KEY = "_sk_sitemap_synced_at";
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { sonorFetch } from './chunk-D6ZC7XKZ.js';
2
+ import { sonorFetch } from './chunk-3E3PPSNR.js';
3
3
  import { useState, useCallback, useEffect } from 'react';
4
4
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
5
5