@sonordev/site-kit 3.7.0 → 3.8.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 (200) hide show
  1. package/agent-manifest.json +1 -1
  2. package/dist/AnalyticsProvider-4KMGMQVD.js +31 -0
  3. package/dist/{AnalyticsProvider-JWXDXOIR.js.map → AnalyticsProvider-4KMGMQVD.js.map} +1 -1
  4. package/dist/AnalyticsProvider-M4BFCRKM.mjs +10 -0
  5. package/dist/{AnalyticsProvider-OIRXQE7O.mjs.map → AnalyticsProvider-M4BFCRKM.mjs.map} +1 -1
  6. package/dist/ChatWidget-I6YFEKW6.js +19 -0
  7. package/dist/{ChatWidget-K2BFJXGB.js.map → ChatWidget-I6YFEKW6.js.map} +1 -1
  8. package/dist/ChatWidget-IV3LIMLK.mjs +10 -0
  9. package/dist/{ChatWidget-FFCUDCT6.mjs.map → ChatWidget-IV3LIMLK.mjs.map} +1 -1
  10. package/dist/EngageWidget-AWVB35ZM.mjs +9 -0
  11. package/dist/{EngageWidget-QKRXI3NB.mjs.map → EngageWidget-AWVB35ZM.mjs.map} +1 -1
  12. package/dist/EngageWidget-TQW76BUU.js +18 -0
  13. package/dist/{EngageWidget-XRXXVVUK.js.map → EngageWidget-TQW76BUU.js.map} +1 -1
  14. package/dist/{SignalCore-6MUAX656.mjs → SignalCore-4FUGFP5E.mjs} +5 -5
  15. package/dist/{SignalCore-6MUAX656.mjs.map → SignalCore-4FUGFP5E.mjs.map} +1 -1
  16. package/dist/{SignalCore-BXCBV6GR.js → SignalCore-VX7ZL5HE.js} +11 -11
  17. package/dist/{SignalCore-BXCBV6GR.js.map → SignalCore-VX7ZL5HE.js.map} +1 -1
  18. package/dist/SitemapSync-CXDEUYM2.mjs +8 -0
  19. package/dist/{SitemapSync-KS7KTJBK.mjs.map → SitemapSync-CXDEUYM2.mjs.map} +1 -1
  20. package/dist/SitemapSync-XRH577AB.js +17 -0
  21. package/dist/{SitemapSync-WEZHTSFL.js.map → SitemapSync-XRH577AB.js.map} +1 -1
  22. package/dist/analytics/index.js +12 -12
  23. package/dist/analytics/index.mjs +5 -5
  24. package/dist/blog/server-ui.js +6 -6
  25. package/dist/blog/server-ui.js.map +1 -1
  26. package/dist/blog/server-ui.mjs +5 -5
  27. package/dist/blog/server-ui.mjs.map +1 -1
  28. package/dist/blog/server.d.mts +20 -1
  29. package/dist/blog/server.d.ts +20 -1
  30. package/dist/blog/server.js +43 -39
  31. package/dist/blog/server.mjs +1 -1
  32. package/dist/{chunk-AJPPCSVW.mjs → chunk-2LQGFCEA.mjs} +3 -3
  33. package/dist/{chunk-AJPPCSVW.mjs.map → chunk-2LQGFCEA.mjs.map} +1 -1
  34. package/dist/{chunk-VZU2EHB6.js → chunk-2WMLHR72.js} +4 -4
  35. package/dist/{chunk-VZU2EHB6.js.map → chunk-2WMLHR72.js.map} +1 -1
  36. package/dist/{chunk-TA6KXHCY.js → chunk-5GJ6V7FI.js} +7 -7
  37. package/dist/{chunk-TA6KXHCY.js.map → chunk-5GJ6V7FI.js.map} +1 -1
  38. package/dist/{chunk-3MYZS6PD.js → chunk-77CIIDE6.js} +15 -3
  39. package/dist/chunk-77CIIDE6.js.map +1 -0
  40. package/dist/{chunk-JFAAPREU.mjs → chunk-7UKIAZ6E.mjs} +4 -4
  41. package/dist/{chunk-JFAAPREU.mjs.map → chunk-7UKIAZ6E.mjs.map} +1 -1
  42. package/dist/{chunk-R3CXRMP7.js → chunk-A2FHTQGB.js} +3 -3
  43. package/dist/{chunk-R3CXRMP7.js.map → chunk-A2FHTQGB.js.map} +1 -1
  44. package/dist/{chunk-AKBGYQLC.js → chunk-ATOUXWFR.js} +15 -15
  45. package/dist/{chunk-AKBGYQLC.js.map → chunk-ATOUXWFR.js.map} +1 -1
  46. package/dist/{chunk-GZHLVOW3.js → chunk-BB2C5JUA.js} +4 -4
  47. package/dist/{chunk-GZHLVOW3.js.map → chunk-BB2C5JUA.js.map} +1 -1
  48. package/dist/{chunk-FP523A7G.mjs → chunk-BVOUZL2S.mjs} +3 -3
  49. package/dist/{chunk-FP523A7G.mjs.map → chunk-BVOUZL2S.mjs.map} +1 -1
  50. package/dist/{chunk-2PQUCJJF.js → chunk-D4V37TBD.js} +5 -5
  51. package/dist/{chunk-2PQUCJJF.js.map → chunk-D4V37TBD.js.map} +1 -1
  52. package/dist/{chunk-XREO3QRA.mjs → chunk-DGFHYNQY.mjs} +3 -3
  53. package/dist/{chunk-XREO3QRA.mjs.map → chunk-DGFHYNQY.mjs.map} +1 -1
  54. package/dist/{chunk-UWL37MUR.mjs → chunk-GH5RO5OW.mjs} +3 -3
  55. package/dist/{chunk-UWL37MUR.mjs.map → chunk-GH5RO5OW.mjs.map} +1 -1
  56. package/dist/{chunk-TQS2X5A3.js → chunk-GSOLN2FC.js} +5 -5
  57. package/dist/{chunk-TQS2X5A3.js.map → chunk-GSOLN2FC.js.map} +1 -1
  58. package/dist/{chunk-ATG4FJY6.js → chunk-H6AU3WKF.js} +35 -3
  59. package/dist/chunk-H6AU3WKF.js.map +1 -0
  60. package/dist/{chunk-CDKWTLWF.mjs → chunk-HQB24QUN.mjs} +4 -4
  61. package/dist/{chunk-CDKWTLWF.mjs.map → chunk-HQB24QUN.mjs.map} +1 -1
  62. package/dist/{chunk-LSWTMMKJ.mjs → chunk-HQJS7VWB.mjs} +3 -3
  63. package/dist/{chunk-LSWTMMKJ.mjs.map → chunk-HQJS7VWB.mjs.map} +1 -1
  64. package/dist/{chunk-C3QMG4HS.js → chunk-I5KJ5YFU.js} +15 -15
  65. package/dist/{chunk-C3QMG4HS.js.map → chunk-I5KJ5YFU.js.map} +1 -1
  66. package/dist/chunk-JVT6CUNN.mjs +6 -0
  67. package/dist/{chunk-2HH4VVJT.mjs.map → chunk-JVT6CUNN.mjs.map} +1 -1
  68. package/dist/{chunk-TZTO5CDS.mjs → chunk-JXN6OCFB.mjs} +3 -3
  69. package/dist/{chunk-TZTO5CDS.mjs.map → chunk-JXN6OCFB.mjs.map} +1 -1
  70. package/dist/chunk-JXT2WWXW.js +8 -0
  71. package/dist/{chunk-SCMHZBTN.js.map → chunk-JXT2WWXW.js.map} +1 -1
  72. package/dist/{chunk-ON6WW7IE.js → chunk-MP6NHVHD.js} +6 -6
  73. package/dist/{chunk-ON6WW7IE.js.map → chunk-MP6NHVHD.js.map} +1 -1
  74. package/dist/{chunk-7UZV6JXD.js → chunk-MRVO3QO3.js} +14 -14
  75. package/dist/{chunk-7UZV6JXD.js.map → chunk-MRVO3QO3.js.map} +1 -1
  76. package/dist/{chunk-XOBW75J2.js → chunk-NEV2OEBF.js} +9 -9
  77. package/dist/{chunk-XOBW75J2.js.map → chunk-NEV2OEBF.js.map} +1 -1
  78. package/dist/{chunk-YE7KZQZ3.mjs → chunk-OLQBP2JQ.mjs} +4 -4
  79. package/dist/{chunk-YE7KZQZ3.mjs.map → chunk-OLQBP2JQ.mjs.map} +1 -1
  80. package/dist/{chunk-6BIPAKL4.mjs → chunk-OVIDFJIK.mjs} +15 -4
  81. package/dist/chunk-OVIDFJIK.mjs.map +1 -0
  82. package/dist/{chunk-GUXB3QH7.mjs → chunk-PA7ENTUZ.mjs} +41 -9
  83. package/dist/chunk-PA7ENTUZ.mjs.map +1 -0
  84. package/dist/{chunk-3K7WF6KB.mjs → chunk-PEFC5T7R.mjs} +8 -8
  85. package/dist/{chunk-3K7WF6KB.mjs.map → chunk-PEFC5T7R.mjs.map} +1 -1
  86. package/dist/{chunk-H23ZT2I2.mjs → chunk-PENNTSJE.mjs} +35 -3
  87. package/dist/chunk-PENNTSJE.mjs.map +1 -0
  88. package/dist/{chunk-4NUHZ24M.js → chunk-Q6KS7FMY.js} +13 -13
  89. package/dist/{chunk-4NUHZ24M.js.map → chunk-Q6KS7FMY.js.map} +1 -1
  90. package/dist/{chunk-5Y5GCSH6.mjs → chunk-R26NFTOR.mjs} +3 -3
  91. package/dist/{chunk-5Y5GCSH6.mjs.map → chunk-R26NFTOR.mjs.map} +1 -1
  92. package/dist/{chunk-NM7L2XKF.mjs → chunk-RSFSXEV2.mjs} +4 -4
  93. package/dist/{chunk-NM7L2XKF.mjs.map → chunk-RSFSXEV2.mjs.map} +1 -1
  94. package/dist/{chunk-AUBFDSTJ.js → chunk-S3J7MEOD.js} +8 -8
  95. package/dist/{chunk-AUBFDSTJ.js.map → chunk-S3J7MEOD.js.map} +1 -1
  96. package/dist/{chunk-34IUDOBC.mjs → chunk-SP3MXF3A.mjs} +34 -5
  97. package/dist/chunk-SP3MXF3A.mjs.map +1 -0
  98. package/dist/{chunk-QPT5QX2W.js → chunk-TA6CENL3.js} +12 -12
  99. package/dist/{chunk-QPT5QX2W.js.map → chunk-TA6CENL3.js.map} +1 -1
  100. package/dist/{chunk-QAYCRXT4.mjs → chunk-TKP3YFNS.mjs} +3 -3
  101. package/dist/{chunk-QAYCRXT4.mjs.map → chunk-TKP3YFNS.mjs.map} +1 -1
  102. package/dist/{chunk-XAWB2HFQ.js → chunk-TMKLH6MY.js} +41 -8
  103. package/dist/chunk-TMKLH6MY.js.map +1 -0
  104. package/dist/{chunk-WQ64SU6E.js → chunk-ULY2QZWA.js} +4 -4
  105. package/dist/{chunk-WQ64SU6E.js.map → chunk-ULY2QZWA.js.map} +1 -1
  106. package/dist/{chunk-ZKAZGLHI.js → chunk-V6CWHT6B.js} +9 -9
  107. package/dist/{chunk-ZKAZGLHI.js.map → chunk-V6CWHT6B.js.map} +1 -1
  108. package/dist/{chunk-54ZC6LPR.mjs → chunk-W5ZYM276.mjs} +3 -3
  109. package/dist/{chunk-54ZC6LPR.mjs.map → chunk-W5ZYM276.mjs.map} +1 -1
  110. package/dist/{chunk-2EYHSGQ3.mjs → chunk-WYRUQCL4.mjs} +3 -3
  111. package/dist/{chunk-2EYHSGQ3.mjs.map → chunk-WYRUQCL4.mjs.map} +1 -1
  112. package/dist/{chunk-HWJF7WMI.js → chunk-XDQP4JQH.js} +14 -14
  113. package/dist/{chunk-HWJF7WMI.js.map → chunk-XDQP4JQH.js.map} +1 -1
  114. package/dist/{chunk-6T4NVCAT.js → chunk-XMBYDIV6.js} +40 -11
  115. package/dist/chunk-XMBYDIV6.js.map +1 -0
  116. package/dist/{chunk-LFFBDQM3.mjs → chunk-Y4V5TFHP.mjs} +4 -4
  117. package/dist/{chunk-LFFBDQM3.mjs.map → chunk-Y4V5TFHP.mjs.map} +1 -1
  118. package/dist/{chunk-2CNKJMGT.mjs → chunk-YUSX3NZA.mjs} +3 -3
  119. package/dist/{chunk-2CNKJMGT.mjs.map → chunk-YUSX3NZA.mjs.map} +1 -1
  120. package/dist/cli/index.js +2 -2
  121. package/dist/cli/index.mjs +1 -1
  122. package/dist/client/index.js +4 -4
  123. package/dist/client/index.mjs +3 -3
  124. package/dist/commerce/index.js +51 -51
  125. package/dist/commerce/index.mjs +6 -6
  126. package/dist/config/index.d.mts +1 -1
  127. package/dist/config/index.d.ts +1 -1
  128. package/dist/config/index.js +2 -2
  129. package/dist/config/index.mjs +1 -1
  130. package/dist/engage/index.js +9 -9
  131. package/dist/engage/index.mjs +6 -6
  132. package/dist/fleet/index.js +8 -8
  133. package/dist/fleet/index.mjs +4 -4
  134. package/dist/forms/index.js +13 -13
  135. package/dist/forms/index.mjs +5 -5
  136. package/dist/images/index.js +11 -11
  137. package/dist/images/index.mjs +4 -4
  138. package/dist/index.js +64 -64
  139. package/dist/index.mjs +10 -10
  140. package/dist/layout/client.js +8 -8
  141. package/dist/layout/client.mjs +7 -7
  142. package/dist/layout/index.js +10 -10
  143. package/dist/layout/index.mjs +8 -8
  144. package/dist/llms/contract.js +9 -9
  145. package/dist/llms/contract.mjs +1 -1
  146. package/dist/llms/index.d.mts +131 -40
  147. package/dist/llms/index.d.ts +131 -40
  148. package/dist/llms/index.js +125 -21
  149. package/dist/llms/index.js.map +1 -1
  150. package/dist/llms/index.mjs +102 -4
  151. package/dist/llms/index.mjs.map +1 -1
  152. package/dist/maps/index.js +5 -5
  153. package/dist/maps/index.mjs +3 -3
  154. package/dist/middleware/index.d.mts +2 -1
  155. package/dist/middleware/index.d.ts +2 -1
  156. package/dist/middleware/index.js +6 -2
  157. package/dist/middleware/index.js.map +1 -1
  158. package/dist/middleware/index.mjs +2 -1
  159. package/dist/middleware/index.mjs.map +1 -1
  160. package/dist/securityHeaders-CwsFdDcJ.d.mts +49 -0
  161. package/dist/securityHeaders-CwsFdDcJ.d.ts +49 -0
  162. package/dist/seo/client.js +5 -5
  163. package/dist/seo/client.mjs +4 -4
  164. package/dist/seo/index.js +7 -7
  165. package/dist/seo/index.mjs +5 -5
  166. package/dist/server/index.js +3 -3
  167. package/dist/server/index.mjs +2 -2
  168. package/dist/signal/index.js +11 -11
  169. package/dist/signal/index.mjs +2 -2
  170. package/dist/sitemap/index.d.mts +8 -1
  171. package/dist/sitemap/index.d.ts +8 -1
  172. package/dist/sitemap/index.js +5 -4
  173. package/dist/sitemap/index.js.map +1 -1
  174. package/dist/sitemap/index.mjs +4 -3
  175. package/dist/sitemap/index.mjs.map +1 -1
  176. package/dist/sync/index.js +16 -16
  177. package/dist/sync/index.mjs +4 -4
  178. package/dist/{types-xcP_owwn.d.ts → writeLLMsTxt-BFaNr4re.d.ts} +53 -1
  179. package/dist/{types-DhCAWUmd.d.mts → writeLLMsTxt-SpMdyHQT.d.mts} +53 -1
  180. package/package.json +1 -1
  181. package/dist/AnalyticsProvider-JWXDXOIR.js +0 -31
  182. package/dist/AnalyticsProvider-OIRXQE7O.mjs +0 -10
  183. package/dist/ChatWidget-FFCUDCT6.mjs +0 -10
  184. package/dist/ChatWidget-K2BFJXGB.js +0 -19
  185. package/dist/EngageWidget-QKRXI3NB.mjs +0 -9
  186. package/dist/EngageWidget-XRXXVVUK.js +0 -18
  187. package/dist/SitemapSync-KS7KTJBK.mjs +0 -8
  188. package/dist/SitemapSync-WEZHTSFL.js +0 -17
  189. package/dist/chunk-2HH4VVJT.mjs +0 -6
  190. package/dist/chunk-34IUDOBC.mjs.map +0 -1
  191. package/dist/chunk-3MYZS6PD.js.map +0 -1
  192. package/dist/chunk-6BIPAKL4.mjs.map +0 -1
  193. package/dist/chunk-6T4NVCAT.js.map +0 -1
  194. package/dist/chunk-ATG4FJY6.js.map +0 -1
  195. package/dist/chunk-GUXB3QH7.mjs.map +0 -1
  196. package/dist/chunk-H23ZT2I2.mjs.map +0 -1
  197. package/dist/chunk-SCMHZBTN.js +0 -8
  198. package/dist/chunk-XAWB2HFQ.js.map +0 -1
  199. package/dist/securityHeaders-nwZ6nP4g.d.mts +0 -24
  200. package/dist/securityHeaders-nwZ6nP4g.d.ts +0 -24
@@ -1,60 +1,60 @@
1
1
  'use strict';
2
2
 
3
- var chunkXOBW75J2_js = require('../chunk-XOBW75J2.js');
4
- require('../chunk-AKBGYQLC.js');
5
- require('../chunk-GZHLVOW3.js');
6
- require('../chunk-SCMHZBTN.js');
3
+ var chunkNEV2OEBF_js = require('../chunk-NEV2OEBF.js');
4
+ require('../chunk-ATOUXWFR.js');
5
+ require('../chunk-BB2C5JUA.js');
6
+ require('../chunk-JXT2WWXW.js');
7
7
  require('../chunk-ZSMWDLMK.js');
8
8
 
9
9
 
10
10
 
11
11
  Object.defineProperty(exports, "BookingWidget", {
12
12
  enumerable: true,
13
- get: function () { return chunkXOBW75J2_js.BookingWidget; }
13
+ get: function () { return chunkNEV2OEBF_js.BookingWidget; }
14
14
  });
15
15
  Object.defineProperty(exports, "createBooking", {
16
16
  enumerable: true,
17
- get: function () { return chunkXOBW75J2_js.createBooking; }
17
+ get: function () { return chunkNEV2OEBF_js.createBooking; }
18
18
  });
19
19
  Object.defineProperty(exports, "createSlotHold", {
20
20
  enumerable: true,
21
- get: function () { return chunkXOBW75J2_js.createSlotHold; }
21
+ get: function () { return chunkNEV2OEBF_js.createSlotHold; }
22
22
  });
23
23
  Object.defineProperty(exports, "detectTimezone", {
24
24
  enumerable: true,
25
- get: function () { return chunkXOBW75J2_js.detectTimezone; }
25
+ get: function () { return chunkNEV2OEBF_js.detectTimezone; }
26
26
  });
27
27
  Object.defineProperty(exports, "fetchAvailability", {
28
28
  enumerable: true,
29
- get: function () { return chunkXOBW75J2_js.fetchAvailability; }
29
+ get: function () { return chunkNEV2OEBF_js.fetchAvailability; }
30
30
  });
31
31
  Object.defineProperty(exports, "fetchAvailableDates", {
32
32
  enumerable: true,
33
- get: function () { return chunkXOBW75J2_js.fetchAvailableDates; }
33
+ get: function () { return chunkNEV2OEBF_js.fetchAvailableDates; }
34
34
  });
35
35
  Object.defineProperty(exports, "fetchBookingTypeDetails", {
36
36
  enumerable: true,
37
- get: function () { return chunkXOBW75J2_js.fetchBookingTypeDetails; }
37
+ get: function () { return chunkNEV2OEBF_js.fetchBookingTypeDetails; }
38
38
  });
39
39
  Object.defineProperty(exports, "fetchBookingTypes", {
40
40
  enumerable: true,
41
- get: function () { return chunkXOBW75J2_js.fetchBookingTypes; }
41
+ get: function () { return chunkNEV2OEBF_js.fetchBookingTypes; }
42
42
  });
43
43
  Object.defineProperty(exports, "formatDate", {
44
44
  enumerable: true,
45
- get: function () { return chunkXOBW75J2_js.formatDate; }
45
+ get: function () { return chunkNEV2OEBF_js.formatDate; }
46
46
  });
47
47
  Object.defineProperty(exports, "formatDuration", {
48
48
  enumerable: true,
49
- get: function () { return chunkXOBW75J2_js.formatDuration; }
49
+ get: function () { return chunkNEV2OEBF_js.formatDuration; }
50
50
  });
51
51
  Object.defineProperty(exports, "formatTime", {
52
52
  enumerable: true,
53
- get: function () { return chunkXOBW75J2_js.formatTime; }
53
+ get: function () { return chunkNEV2OEBF_js.formatTime; }
54
54
  });
55
55
  Object.defineProperty(exports, "releaseSlotHold", {
56
56
  enumerable: true,
57
- get: function () { return chunkXOBW75J2_js.releaseSlotHold; }
57
+ get: function () { return chunkNEV2OEBF_js.releaseSlotHold; }
58
58
  });
59
59
  //# sourceMappingURL=index.js.map
60
60
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
- export { BookingWidget, createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, releaseSlotHold } from '../chunk-2CNKJMGT.mjs';
2
- import '../chunk-NM7L2XKF.mjs';
3
- import '../chunk-QAYCRXT4.mjs';
4
- import '../chunk-2HH4VVJT.mjs';
1
+ export { BookingWidget, createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, releaseSlotHold } from '../chunk-YUSX3NZA.mjs';
2
+ import '../chunk-RSFSXEV2.mjs';
3
+ import '../chunk-TKP3YFNS.mjs';
4
+ import '../chunk-JVT6CUNN.mjs';
5
5
  import '../chunk-4XPGGLVP.mjs';
6
6
  //# sourceMappingURL=index.mjs.map
7
7
  //# sourceMappingURL=index.mjs.map
@@ -323,4 +323,56 @@ interface LLMsDataResponse {
323
323
  portfolio?: LLMPortfolioItem[];
324
324
  }
325
325
 
326
- export type { AEOBlockProps as A, ContentProvenance as C, GenerateLLMSTxtOptions as G, LLMsDataResponse as L, SpeakableSchemaProps as S, LLMSTxtContent as a, SpeakableConfig as b, AEOSummaryProps as c, AEODefinitionProps as d, AEOClaimProps as e, LLMBusinessInfo as f, LLMService as g, LLMFAQItem as h, LLMPageSummary as i, LLMContactInfo as j, AEOEntityProps as k, AEOProvenanceListProps as l, AEOCitedContentProps as m, LLMPortfolioItem as n };
326
+ /**
327
+ * @sonordev/site-kit/llms - Build-Time Write
328
+ *
329
+ * Fetches AI-optimized llms.txt from Portal API and writes to public/llms.txt
330
+ * at build time. Integrates with sitemap flow when optimizedLLMsTxt is enabled.
331
+ */
332
+
333
+ interface LLMsCustomSection {
334
+ title: string;
335
+ content: string;
336
+ }
337
+ interface WriteLLMsTxtOptions {
338
+ /** Output directory (default: public, relative to cwd) */
339
+ outputDir?: string;
340
+ /** Write llms-full.txt as well */
341
+ full?: boolean;
342
+ /** Portal API URL */
343
+ apiUrl?: string;
344
+ /** Portal API key */
345
+ apiKey?: string;
346
+ /** Fallback to non-optimized when API fails */
347
+ fallbackToLocal?: boolean;
348
+ /** When Portal returns empty services/faq/pages, use this to supply local site data */
349
+ getLocalData?: () => Promise<LLMsDataResponse | null>;
350
+ /** Forward to GET /api/public/llms/txt and align local fallback with site-kit strict page notes */
351
+ publicSummaryOnly?: boolean;
352
+ /**
353
+ * Site-authored sections appended to llms-full.txt (never llms.txt — that
354
+ * file stays a compact index). Applied on BOTH content paths: appended to
355
+ * the Portal-optimized markdown, and forwarded to the local generator's
356
+ * customSections on fallback. A function form is resolved at write time so
357
+ * sites can build sections from local data (e.g. a verified citation
358
+ * registry → a "Sourced facts" section via formatSourcedFactsSection).
359
+ * Sections are only ever appended to real base content — they can never
360
+ * cause a customs-only file to be written.
361
+ */
362
+ customSections?: LLMsCustomSection[] | (() => Promise<LLMsCustomSection[] | null> | LLMsCustomSection[] | null);
363
+ }
364
+ /**
365
+ * Fetch optimized llms.txt from Portal and write to public/llms.txt
366
+ * Called at build time after sitemap sync (when optimizedLLMsTxt is enabled)
367
+ *
368
+ * Never persists a failure stub: when neither the Portal API nor local data
369
+ * yields real content, the write is skipped entirely so a previously
370
+ * generated (or committed) file keeps serving.
371
+ */
372
+ declare function writeLLMsTxtToPublic(options?: WriteLLMsTxtOptions): Promise<{
373
+ success: boolean;
374
+ path: string;
375
+ optimized: boolean;
376
+ }>;
377
+
378
+ export { type AEOBlockProps as A, type ContentProvenance as C, type GenerateLLMSTxtOptions as G, type LLMsDataResponse as L, type SpeakableSchemaProps as S, type WriteLLMsTxtOptions as W, type LLMSTxtContent as a, type LLMsCustomSection as b, type SpeakableConfig as c, type AEOSummaryProps as d, type AEODefinitionProps as e, type AEOClaimProps as f, type LLMBusinessInfo as g, type LLMService as h, type LLMFAQItem as i, type LLMPageSummary as j, type LLMContactInfo as k, type AEOEntityProps as l, type AEOProvenanceListProps as m, type AEOCitedContentProps as n, type LLMPortfolioItem as o, writeLLMsTxtToPublic as w };
@@ -323,4 +323,56 @@ interface LLMsDataResponse {
323
323
  portfolio?: LLMPortfolioItem[];
324
324
  }
325
325
 
326
- export type { AEOBlockProps as A, ContentProvenance as C, GenerateLLMSTxtOptions as G, LLMsDataResponse as L, SpeakableSchemaProps as S, LLMSTxtContent as a, SpeakableConfig as b, AEOSummaryProps as c, AEODefinitionProps as d, AEOClaimProps as e, LLMBusinessInfo as f, LLMService as g, LLMFAQItem as h, LLMPageSummary as i, LLMContactInfo as j, AEOEntityProps as k, AEOProvenanceListProps as l, AEOCitedContentProps as m, LLMPortfolioItem as n };
326
+ /**
327
+ * @sonordev/site-kit/llms - Build-Time Write
328
+ *
329
+ * Fetches AI-optimized llms.txt from Portal API and writes to public/llms.txt
330
+ * at build time. Integrates with sitemap flow when optimizedLLMsTxt is enabled.
331
+ */
332
+
333
+ interface LLMsCustomSection {
334
+ title: string;
335
+ content: string;
336
+ }
337
+ interface WriteLLMsTxtOptions {
338
+ /** Output directory (default: public, relative to cwd) */
339
+ outputDir?: string;
340
+ /** Write llms-full.txt as well */
341
+ full?: boolean;
342
+ /** Portal API URL */
343
+ apiUrl?: string;
344
+ /** Portal API key */
345
+ apiKey?: string;
346
+ /** Fallback to non-optimized when API fails */
347
+ fallbackToLocal?: boolean;
348
+ /** When Portal returns empty services/faq/pages, use this to supply local site data */
349
+ getLocalData?: () => Promise<LLMsDataResponse | null>;
350
+ /** Forward to GET /api/public/llms/txt and align local fallback with site-kit strict page notes */
351
+ publicSummaryOnly?: boolean;
352
+ /**
353
+ * Site-authored sections appended to llms-full.txt (never llms.txt — that
354
+ * file stays a compact index). Applied on BOTH content paths: appended to
355
+ * the Portal-optimized markdown, and forwarded to the local generator's
356
+ * customSections on fallback. A function form is resolved at write time so
357
+ * sites can build sections from local data (e.g. a verified citation
358
+ * registry → a "Sourced facts" section via formatSourcedFactsSection).
359
+ * Sections are only ever appended to real base content — they can never
360
+ * cause a customs-only file to be written.
361
+ */
362
+ customSections?: LLMsCustomSection[] | (() => Promise<LLMsCustomSection[] | null> | LLMsCustomSection[] | null);
363
+ }
364
+ /**
365
+ * Fetch optimized llms.txt from Portal and write to public/llms.txt
366
+ * Called at build time after sitemap sync (when optimizedLLMsTxt is enabled)
367
+ *
368
+ * Never persists a failure stub: when neither the Portal API nor local data
369
+ * yields real content, the write is skipped entirely so a previously
370
+ * generated (or committed) file keeps serving.
371
+ */
372
+ declare function writeLLMsTxtToPublic(options?: WriteLLMsTxtOptions): Promise<{
373
+ success: boolean;
374
+ path: string;
375
+ optimized: boolean;
376
+ }>;
377
+
378
+ export { type AEOBlockProps as A, type ContentProvenance as C, type GenerateLLMSTxtOptions as G, type LLMsDataResponse as L, type SpeakableSchemaProps as S, type WriteLLMsTxtOptions as W, type LLMSTxtContent as a, type LLMsCustomSection as b, type SpeakableConfig as c, type AEOSummaryProps as d, type AEODefinitionProps as e, type AEOClaimProps as f, type LLMBusinessInfo as g, type LLMService as h, type LLMFAQItem as i, type LLMPageSummary as j, type LLMContactInfo as k, type AEOEntityProps as l, type AEOProvenanceListProps as m, type AEOCitedContentProps as n, type LLMPortfolioItem as o, writeLLMsTxtToPublic as w };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonordev/site-kit",
3
- "version": "3.7.0",
3
+ "version": "3.8.0",
4
4
  "description": "Complete client-side integration kit for Sonor - SEO, Analytics, Engage, Forms, Blog",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,31 +0,0 @@
1
- 'use strict';
2
-
3
- var chunk4NUHZ24M_js = require('./chunk-4NUHZ24M.js');
4
- require('./chunk-HMFFAUCD.js');
5
- require('./chunk-XB57AM6T.js');
6
- require('./chunk-VJMPIRSD.js');
7
- require('./chunk-AKBGYQLC.js');
8
- require('./chunk-GZHLVOW3.js');
9
- require('./chunk-SCMHZBTN.js');
10
- require('./chunk-ZSMWDLMK.js');
11
-
12
-
13
-
14
- Object.defineProperty(exports, "AnalyticsProvider", {
15
- enumerable: true,
16
- get: function () { return chunk4NUHZ24M_js.AnalyticsProvider; }
17
- });
18
- Object.defineProperty(exports, "useAnalytics", {
19
- enumerable: true,
20
- get: function () { return chunk4NUHZ24M_js.useAnalytics; }
21
- });
22
- Object.defineProperty(exports, "useAnalyticsOptional", {
23
- enumerable: true,
24
- get: function () { return chunk4NUHZ24M_js.useAnalyticsOptional; }
25
- });
26
- Object.defineProperty(exports, "useTrackEvent", {
27
- enumerable: true,
28
- get: function () { return chunk4NUHZ24M_js.useTrackEvent; }
29
- });
30
- //# sourceMappingURL=AnalyticsProvider-JWXDXOIR.js.map
31
- //# sourceMappingURL=AnalyticsProvider-JWXDXOIR.js.map
@@ -1,10 +0,0 @@
1
- export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-UWL37MUR.mjs';
2
- import './chunk-3DPXOZAU.mjs';
3
- import './chunk-AX4AROLH.mjs';
4
- import './chunk-6EDVCUAG.mjs';
5
- import './chunk-NM7L2XKF.mjs';
6
- import './chunk-QAYCRXT4.mjs';
7
- import './chunk-2HH4VVJT.mjs';
8
- import './chunk-4XPGGLVP.mjs';
9
- //# sourceMappingURL=AnalyticsProvider-OIRXQE7O.mjs.map
10
- //# sourceMappingURL=AnalyticsProvider-OIRXQE7O.mjs.map
@@ -1,10 +0,0 @@
1
- export { ChatWidget } from './chunk-CDKWTLWF.mjs';
2
- import './chunk-5Y5GCSH6.mjs';
3
- import './chunk-X3S6KXAP.mjs';
4
- import './chunk-6EDVCUAG.mjs';
5
- import './chunk-NM7L2XKF.mjs';
6
- import './chunk-QAYCRXT4.mjs';
7
- import './chunk-2HH4VVJT.mjs';
8
- import './chunk-4XPGGLVP.mjs';
9
- //# sourceMappingURL=ChatWidget-FFCUDCT6.mjs.map
10
- //# sourceMappingURL=ChatWidget-FFCUDCT6.mjs.map
@@ -1,19 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkC3QMG4HS_js = require('./chunk-C3QMG4HS.js');
4
- require('./chunk-ZKAZGLHI.js');
5
- require('./chunk-V6NVBFEP.js');
6
- require('./chunk-VJMPIRSD.js');
7
- require('./chunk-AKBGYQLC.js');
8
- require('./chunk-GZHLVOW3.js');
9
- require('./chunk-SCMHZBTN.js');
10
- require('./chunk-ZSMWDLMK.js');
11
-
12
-
13
-
14
- Object.defineProperty(exports, "ChatWidget", {
15
- enumerable: true,
16
- get: function () { return chunkC3QMG4HS_js.ChatWidget; }
17
- });
18
- //# sourceMappingURL=ChatWidget-K2BFJXGB.js.map
19
- //# sourceMappingURL=ChatWidget-K2BFJXGB.js.map
@@ -1,9 +0,0 @@
1
- export { EngageWidget } from './chunk-LFFBDQM3.mjs';
2
- import './chunk-AX4AROLH.mjs';
3
- import './chunk-6EDVCUAG.mjs';
4
- import './chunk-NM7L2XKF.mjs';
5
- import './chunk-QAYCRXT4.mjs';
6
- import './chunk-2HH4VVJT.mjs';
7
- import './chunk-4XPGGLVP.mjs';
8
- //# sourceMappingURL=EngageWidget-QKRXI3NB.mjs.map
9
- //# sourceMappingURL=EngageWidget-QKRXI3NB.mjs.map
@@ -1,18 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkON6WW7IE_js = require('./chunk-ON6WW7IE.js');
4
- require('./chunk-XB57AM6T.js');
5
- require('./chunk-VJMPIRSD.js');
6
- require('./chunk-AKBGYQLC.js');
7
- require('./chunk-GZHLVOW3.js');
8
- require('./chunk-SCMHZBTN.js');
9
- require('./chunk-ZSMWDLMK.js');
10
-
11
-
12
-
13
- Object.defineProperty(exports, "EngageWidget", {
14
- enumerable: true,
15
- get: function () { return chunkON6WW7IE_js.EngageWidget; }
16
- });
17
- //# sourceMappingURL=EngageWidget-XRXXVVUK.js.map
18
- //# sourceMappingURL=EngageWidget-XRXXVVUK.js.map
@@ -1,8 +0,0 @@
1
- export { SitemapSync } from './chunk-FP523A7G.mjs';
2
- import './chunk-QJU6HBSK.mjs';
3
- import './chunk-NM7L2XKF.mjs';
4
- import './chunk-QAYCRXT4.mjs';
5
- import './chunk-2HH4VVJT.mjs';
6
- import './chunk-4XPGGLVP.mjs';
7
- //# sourceMappingURL=SitemapSync-KS7KTJBK.mjs.map
8
- //# sourceMappingURL=SitemapSync-KS7KTJBK.mjs.map
@@ -1,17 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkTQS2X5A3_js = require('./chunk-TQS2X5A3.js');
4
- require('./chunk-JEOKDUPQ.js');
5
- require('./chunk-AKBGYQLC.js');
6
- require('./chunk-GZHLVOW3.js');
7
- require('./chunk-SCMHZBTN.js');
8
- require('./chunk-ZSMWDLMK.js');
9
-
10
-
11
-
12
- Object.defineProperty(exports, "SitemapSync", {
13
- enumerable: true,
14
- get: function () { return chunkTQS2X5A3_js.SitemapSync; }
15
- });
16
- //# sourceMappingURL=SitemapSync-WEZHTSFL.js.map
17
- //# sourceMappingURL=SitemapSync-WEZHTSFL.js.map
@@ -1,6 +0,0 @@
1
- // src/shared/version.ts
2
- var SITE_KIT_VERSION = "3.7.0";
3
-
4
- export { SITE_KIT_VERSION };
5
- //# sourceMappingURL=chunk-2HH4VVJT.mjs.map
6
- //# sourceMappingURL=chunk-2HH4VVJT.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/llms/api.ts","../src/llms/generateLLMsTxt.ts","../src/llms/writeLLMsTxt.ts"],"names":[],"mappings":"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","file":"chunk-34IUDOBC.mjs","sourcesContent":["/**\n * @sonordev/site-kit/llms - API Functions\n * \n * Data fetching for LLM visibility content.\n * Pulls from Signal knowledge base and project data.\n */\n\nimport { cache } from 'react'\nimport { LLM_GEO_CONTRACT_VERSION } from './contract'\nimport type { LLMsDataResponse, LLMBusinessInfo, LLMContactInfo, LLMService, LLMFAQItem, LLMPageSummary } from './types'\n\n// ============================================\n// API Config\n// ============================================\n\nfunction getApiConfig() {\n // Use site-kit globals if available, otherwise fall back to env vars\n const apiUrl = (typeof window !== 'undefined' && (window as any).__SITE_KIT_API_URL__)\n || process.env.SONOR_API_URL\n || 'https://api.sonor.io'\n\n const apiKey = (typeof window !== 'undefined' && (window as any).__SITE_KIT_API_KEY__)\n || process.env.SONOR_API_KEY\n || ''\n \n return { apiUrl, apiKey }\n}\n\nasync function apiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/llms: No API key configured. Set SONOR_API_KEY.')\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 3600 }, // Next.js fetch cache\n } as RequestInit)\n \n if (!response.ok) {\n console.error(`@sonordev/llms: API error: ${response.statusText}`)\n return null\n }\n\n const json = await response.json()\n return json\n } catch (error) {\n console.error('@sonordev/llms: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch all LLM visibility data for a project - cached per request\n * This is the main data source for llms.txt generation\n * \n * @param projectId - Optional project ID (API key identifies project if omitted)\n */\nexport const getLLMsData = cache(async (\n projectId?: string\n): Promise<LLMsDataResponse | null> => {\n const data = await apiGet<LLMsDataResponse>(`/api/public/llms/data`)\n if (\n data?.meta &&\n data.meta.contract_version != null &&\n data.meta.contract_version !== LLM_GEO_CONTRACT_VERSION &&\n typeof process !== 'undefined' &&\n process.env.NODE_ENV !== 'production'\n ) {\n console.warn(\n `[site-kit/llms] API meta.contract_version (${data.meta.contract_version}) !== site-kit LLM_GEO_CONTRACT_VERSION (${LLM_GEO_CONTRACT_VERSION}).`,\n )\n }\n return data\n})\n\n/**\n * Fetch business info only - cached per request\n */\nexport const getBusinessInfo = cache(async (\n projectId?: string\n): Promise<LLMBusinessInfo | null> => {\n const result = await apiGet<{ business: LLMBusinessInfo }>(`/api/public/llms/business`)\n return result?.business || null\n})\n\n/**\n * Fetch services list - cached per request\n */\nexport const getServices = cache(async (\n projectId?: string\n): Promise<LLMService[]> => {\n const result = await apiGet<{ services: LLMService[] }>(`/api/public/llms/services`)\n return result?.services || []\n})\n\n/**\n * Fetch FAQ items - cached per request\n */\nexport const getFAQItems = cache(async (\n projectId?: string,\n limit?: number\n): Promise<LLMFAQItem[]> => {\n const endpoint = limit \n ? `/api/public/llms/faq?limit=${limit}`\n : '/api/public/llms/faq'\n const result = await apiGet<{ faq: LLMFAQItem[] }>(endpoint)\n return result?.faq || []\n})\n\n/**\n * Fetch page summaries for sitemap - cached per request\n */\nexport const getPageSummaries = cache(async (\n projectId?: string,\n limit?: number\n): Promise<LLMPageSummary[]> => {\n const endpoint = limit \n ? `/api/public/llms/pages?limit=${limit}`\n : '/api/public/llms/pages'\n const result = await apiGet<{ pages: LLMPageSummary[] }>(endpoint)\n return result?.pages || []\n})\n\n/**\n * Fetch AI-optimized llms.txt markdown from Portal API (build-time)\n * Used by writeLLMsTxtToPublic for static file generation\n */\nexport async function getOptimizedLLMsTxt(options?: {\n full?: boolean\n /** Matches Portal GET /api/public/llms/txt?publicSummaryOnly=true */\n publicSummaryOnly?: boolean\n apiUrl?: string\n apiKey?: string\n}): Promise<string | null> {\n const apiUrl = options?.apiUrl\n || (typeof process !== 'undefined' && process.env?.SONOR_API_URL)\n || 'https://api.sonor.io'\n const apiKey = options?.apiKey\n || (typeof process !== 'undefined' && process.env?.SONOR_API_KEY)\n || ''\n\n if (!apiKey) {\n console.error('@sonordev/llms: No API key configured for getOptimizedLLMsTxt')\n return null\n }\n\n const params = new URLSearchParams()\n if (options?.full) params.set('full', 'true')\n if (options?.publicSummaryOnly) params.set('publicSummaryOnly', 'true')\n const qs = params.toString()\n const endpoint = `/api/public/llms/txt${qs ? `?${qs}` : ''}`\n\n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'text/plain',\n 'x-api-key': apiKey,\n },\n })\n\n if (!response.ok) {\n console.error(`@sonordev/llms: Optimized txt API error: ${response.status} ${response.statusText}`)\n return null\n }\n\n return await response.text()\n } catch (error) {\n console.error('@sonordev/llms: Failed to fetch optimized llms.txt:', error)\n return null\n }\n}\n","/**\n * @sonordev/site-kit/llms - llms.txt Generator\n * \n * Generates llms.txt content following the llms.txt specification.\n * https://llmstxt.org/\n * \n * The llms.txt file provides a markdown-formatted overview of a website\n * specifically designed for LLM consumption. It helps AI systems understand\n * what a business does, what services it offers, and how to answer questions.\n */\n\nimport { getLLMsData } from './api'\nimport type {\n GenerateLLMSTxtOptions,\n LLMSTxtContent,\n LLMsDataResponse,\n LLMBusinessInfo,\n LLMContactInfo,\n LLMService,\n LLMFAQItem,\n LLMPageSummary,\n LLMPortfolioItem,\n} from './types'\nimport type { SEOEntity } from '../seo/types'\nimport type { LLMsPayloadMeta } from './contract'\nimport {\n LLM_GEO_CONTRACT_VERSION,\n sanitizeLlmsDisclaimerLine,\n sanitizeLlmsPublicSummary,\n sanitizePrimaryLanguageTag,\n} from './contract'\n\nfunction mergeLlmsMeta(\n fallback: LLMsPayloadMeta | null | undefined,\n primary: LLMsPayloadMeta | null | undefined,\n): LLMsPayloadMeta | undefined {\n if (!primary && !fallback) return undefined\n if (!primary) return fallback ?? undefined\n if (!fallback) return primary\n return {\n contract_version: primary.contract_version ?? fallback.contract_version,\n last_updated: primary.last_updated ?? fallback.last_updated ?? null,\n primary_language: primary.primary_language ?? fallback.primary_language ?? null,\n llms_disclaimer: primary.llms_disclaimer ?? fallback.llms_disclaimer ?? null,\n }\n}\n\n/**\n * Single source of truth for the llms.txt link base (site origin).\n * Precedence: explicit `baseUrl` option → Portal/local `business.website` →\n * NEXT_PUBLIC_SITE_URL → SITE_URL. Intentionally never derived from request\n * headers — touching the Request would force the /llms.txt route dynamic and\n * break static prerendering on consumer sites.\n */\nfunction resolveBaseUrl(\n optionBaseUrl: string | undefined,\n businessWebsite: string | undefined | null,\n): string {\n const candidate =\n optionBaseUrl ||\n businessWebsite ||\n process.env.NEXT_PUBLIC_SITE_URL ||\n process.env.SITE_URL ||\n ''\n return candidate.trim().replace(/\\/+$/, '')\n}\n\n/**\n * Merge Portal data with local data. Portal fields take precedence; local fills gaps when Portal is empty.\n */\nfunction mergeLLMsData(\n portal: Partial<LLMsDataResponse> | null,\n local: LLMsDataResponse | null\n): LLMsDataResponse | null {\n if (!local) return portal as LLMsDataResponse | null\n if (!portal) return local\n return {\n meta: mergeLlmsMeta(local.meta, portal.meta),\n business: portal.business ?? local.business,\n contact: portal.contact ?? local.contact,\n services: (portal.services?.length ? portal.services : local.services) ?? [],\n faq: (portal.faq?.length ? portal.faq : local.faq) ?? [],\n pages: (portal.pages?.length ? portal.pages : local.pages) ?? [],\n portfolio: (portal.portfolio?.length ? portal.portfolio : local.portfolio) ?? [],\n }\n}\n\n/**\n * Generate llms.txt content from Portal data\n * \n * @example\n * ```ts\n * // app/llms.txt/route.ts\n * import { generateLLMsTxt } from '@sonordev/site-kit/llms'\n * \n * export async function GET() {\n * const { markdown } = await generateLLMsTxt({\n * projectId: process.env.SONOR_API_KEY!\n * })\n * \n * return new Response(markdown, {\n * headers: { 'Content-Type': 'text/plain; charset=utf-8' }\n * })\n * }\n * ```\n */\nexport async function generateLLMsTxt(\n options: GenerateLLMSTxtOptions\n): Promise<LLMSTxtContent> {\n const {\n projectId,\n baseUrl: baseUrlOption,\n getLocalData,\n includeBusinessInfo = true,\n includeServices = true,\n includeFAQ = true,\n includePages = true,\n includeContact = true,\n includePortfolio = true,\n includeEntities = true,\n maxFAQItems = 20,\n maxPages = 50,\n maxPortfolioItems = 20,\n maxEntities = 50,\n maxArticlesPerCluster = 5,\n customSections = [],\n optionalPagePaths = [],\n linkToFullLlms = false,\n fullLlmsTxtPath = '/llms-full.txt',\n pageListNotesFromPublicSummaryOnly = false,\n headerPrimaryLanguage,\n headerDisclaimer,\n } = options\n\n // Fetch from Portal first\n let data = await getLLMsData(projectId)\n\n // Use local data when Portal returns null or empty services\n const useLocal = getLocalData && (!data || !data.services?.length)\n if (useLocal && getLocalData) {\n try {\n const local = await getLocalData()\n data = mergeLLMsData(data ?? null, local)\n } catch (err) {\n console.warn('[site-kit] getLocalData failed:', err)\n }\n }\n \n if (!data) {\n // Return minimal content if no data\n return {\n markdown: '# Website\\n\\n> Information not available.',\n metadata: {\n generated_at: new Date().toISOString(),\n project_id: projectId || '',\n sections: [],\n }\n }\n }\n\n const headerMeta = buildHeaderMeta(\n data.meta,\n headerPrimaryLanguage,\n headerDisclaimer,\n )\n\n const baseUrl = resolveBaseUrl(baseUrlOption, data.business?.website)\n\n const sections: string[] = []\n const sectionNames: string[] = []\n const attemptedSections: string[] = []\n const failedSections: string[] = []\n\n // ========================================\n // Header Section (H1 + blockquote summary)\n // ========================================\n if (includeBusinessInfo && data.business) {\n const header = generateHeaderSection(data.business, headerMeta, baseUrl)\n sections.push(header)\n sectionNames.push('header')\n }\n\n // ========================================\n // About Section\n // ========================================\n if (includeBusinessInfo && data.business?.description) {\n const about = generateAboutSection(data.business)\n sections.push(about)\n sectionNames.push('about')\n }\n\n // ========================================\n // Services Section\n // ========================================\n if (includeServices && data.services?.length > 0) {\n const services = generateServicesSection(data.services)\n sections.push(services)\n sectionNames.push('services')\n }\n\n // ========================================\n // Portfolio / Case Studies Section\n // ========================================\n if (includePortfolio) {\n let portfolioItems = data.portfolio || []\n\n // If LLMs data didn't include portfolio, fetch directly from the portfolio endpoint\n if (portfolioItems.length === 0) {\n attemptedSections.push('portfolio')\n try {\n const apiUrl = process.env.SONOR_API_URL || 'https://api.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || ''\n if (apiKey) {\n const response = await fetch(`${apiUrl}/api/public/portfolio/items`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n })\n if (response.ok) {\n const result = await response.json()\n const items = result?.portfolioItems || result?.items || result || []\n portfolioItems = items.filter((item: any) => item.status === 'published')\n }\n }\n } catch (err) {\n console.warn('[site-kit/llms] Portfolio section failed:', err)\n failedSections.push('portfolio')\n }\n }\n\n if (portfolioItems.length > 0) {\n const portfolio = generatePortfolioSection(\n portfolioItems.slice(0, maxPortfolioItems),\n baseUrl\n )\n sections.push(portfolio)\n sectionNames.push('portfolio')\n }\n }\n\n // ========================================\n // Contact Section\n // ========================================\n if (includeContact && data.contact) {\n const contact = generateContactSection(data.contact)\n sections.push(contact)\n sectionNames.push('contact')\n }\n\n // ========================================\n // FAQ Section\n // ========================================\n if (includeFAQ && data.faq?.length > 0) {\n const faq = generateFAQSection(data.faq.slice(0, maxFAQItems))\n sections.push(faq)\n sectionNames.push('faq')\n }\n\n // ========================================\n // Pages Section (sitemap-like index)\n // ========================================\n if (includePages && data.pages?.length > 0) {\n const pages = generatePagesSection(\n data.pages.slice(0, maxPages),\n baseUrl,\n pageListNotesFromPublicSummaryOnly,\n )\n sections.push(pages)\n sectionNames.push('pages')\n }\n\n if (optionalPagePaths.length > 0 && baseUrl) {\n const opt = generateOptionalPagesSection(\n optionalPagePaths,\n data.pages || [],\n baseUrl,\n )\n if (opt) {\n sections.push(opt)\n sectionNames.push('optional')\n }\n }\n\n if (linkToFullLlms && baseUrl) {\n const fullPath = fullLlmsTxtPath.startsWith('/') ? fullLlmsTxtPath : `/${fullLlmsTxtPath}`\n const fullUrl = fullPath.startsWith('http') ? fullPath : `${baseUrl}${fullPath}`\n sections.push(\n `## Full context\\n\\n- [llms-full.txt](${fullUrl}): Expanded page index and FAQ for large-context systems.`,\n )\n sectionNames.push('full-context')\n }\n\n // ========================================\n // Knowledge Graph + Topic Clusters (parallel)\n // ========================================\n {\n type OptionalResult =\n | { kind: 'entities'; entities: SEOEntity[]; primaryEntity: SEOEntity | null }\n | { kind: 'clusters'; clusters: any[] }\n\n const optionalFetches: Promise<OptionalResult | null>[] = []\n\n if (includeEntities) {\n attemptedSections.push('knowledge-graph')\n optionalFetches.push(\n import('../seo/server-api')\n .then(async ({ getEntities, getPrimaryEntity }) => {\n const [entities, primaryEntity] = await Promise.all([\n getEntities().then(e => e.slice(0, maxEntities)),\n getPrimaryEntity(),\n ])\n return { kind: 'entities' as const, entities, primaryEntity }\n })\n .catch((err) => {\n console.warn('[site-kit/llms] Knowledge graph section failed:', err)\n failedSections.push('knowledge-graph')\n return null\n }),\n )\n }\n\n attemptedSections.push('topic-clusters')\n optionalFetches.push(\n import('../blog/server-core')\n .then(async ({ getTopicClusters }) => {\n const clusters = await getTopicClusters()\n return { kind: 'clusters' as const, clusters }\n })\n .catch((err) => {\n console.warn('[site-kit/llms] Topic clusters section failed:', err)\n failedSections.push('topic-clusters')\n return null\n }),\n )\n\n const settled = await Promise.all(optionalFetches)\n\n for (const result of settled) {\n if (!result) continue\n\n if (result.kind === 'entities') {\n if (result.entities.length > 0 || result.primaryEntity) {\n const entitySection = generateEntitySection(result.entities, result.primaryEntity, false)\n sections.push(entitySection)\n sectionNames.push('knowledge-graph')\n }\n }\n\n if (result.kind === 'clusters' && result.clusters.length > 0) {\n const clusterLines: string[] = ['## Topic Clusters', '']\n clusterLines.push('Organized content collections providing comprehensive coverage of key topics.', '')\n for (const cluster of result.clusters) {\n clusterLines.push(`### ${cluster.cluster_name}`)\n clusterLines.push(`Topic: ${cluster.core_topic}`)\n if (cluster.geo_target) clusterLines.push(`Area: ${cluster.geo_target}`)\n clusterLines.push(`Articles: ${cluster.article_count}`)\n if (cluster.target_service_page) {\n clusterLines.push(`Service page: ${baseUrl}${cluster.target_service_page}`)\n }\n\n // Enriched: list pillar page and recent articles\n if (cluster.pillar) {\n const pillarUrl = cluster.pillar.slug ? `${baseUrl}/blog/${cluster.pillar.slug}` : ''\n clusterLines.push(`Pillar: [${cluster.pillar.title || cluster.cluster_name}](${pillarUrl})`)\n }\n const supports = (cluster.supports || []) as any[]\n if (supports.length > 0) {\n const sorted = [...supports]\n .sort((a, b) => (b.published_at || '').localeCompare(a.published_at || ''))\n .slice(0, maxArticlesPerCluster)\n for (const article of sorted) {\n const articleUrl = article.slug ? `${baseUrl}/blog/${article.slug}` : ''\n const dateStr = article.published_at\n ? ` (${new Date(article.published_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })})`\n : ''\n clusterLines.push(`- [${article.title}](${articleUrl})${dateStr}`)\n }\n }\n\n clusterLines.push('')\n }\n sections.push(clusterLines.join('\\n'))\n sectionNames.push('topic-clusters')\n }\n }\n }\n\n // ========================================\n // Custom Sections\n // ========================================\n for (const custom of customSections) {\n sections.push(`## ${custom.title}\\n\\n${custom.content}`)\n sectionNames.push(custom.title.toLowerCase().replace(/\\s+/g, '-'))\n }\n\n return {\n markdown: sections.join('\\n\\n---\\n\\n'),\n metadata: {\n generated_at: new Date().toISOString(),\n project_id: projectId || '',\n sections: sectionNames,\n attempted_sections: attemptedSections.length ? attemptedSections : undefined,\n failed_sections: failedSections.length ? failedSections : undefined,\n }\n }\n}\n\n/**\n * Generate llms-full.txt with comprehensive knowledge dump\n * Use this for AI systems that can handle larger context\n */\nexport async function generateLLMsFullTxt(\n options: GenerateLLMSTxtOptions\n): Promise<LLMSTxtContent> {\n return generateLLMsTxt({\n ...options,\n includeBusinessInfo: true,\n includeServices: true,\n includeFAQ: true,\n includePages: true,\n includeContact: true,\n includePortfolio: true,\n includeEntities: true,\n maxFAQItems: 100,\n maxPages: 200,\n maxPortfolioItems: 50,\n maxEntities: 200,\n })\n}\n\n// ============================================\n// Section Generators\n// ============================================\n\nfunction buildHeaderMeta(\n base: LLMsPayloadMeta | null | undefined,\n primaryLanguageOverride?: string,\n disclaimerOverride?: string,\n): LLMsPayloadMeta | undefined {\n if (primaryLanguageOverride === undefined && disclaimerOverride === undefined) {\n return base ?? undefined\n }\n const merged: LLMsPayloadMeta = {\n contract_version: base?.contract_version ?? LLM_GEO_CONTRACT_VERSION,\n last_updated: base?.last_updated ?? null,\n primary_language: base?.primary_language ?? null,\n llms_disclaimer: base?.llms_disclaimer ?? null,\n }\n if (primaryLanguageOverride !== undefined) {\n const pl = sanitizePrimaryLanguageTag(primaryLanguageOverride)\n merged.primary_language = pl ?? merged.primary_language\n }\n if (disclaimerOverride !== undefined) {\n const d = sanitizeLlmsDisclaimerLine(disclaimerOverride)\n merged.llms_disclaimer = d ?? merged.llms_disclaimer\n }\n return merged\n}\n\nfunction generateHeaderSection(\n business: LLMBusinessInfo,\n meta?: LLMsPayloadMeta | null,\n resolvedBaseUrl?: string,\n): string {\n const lines: string[] = []\n \n // H1 with business name\n lines.push(`# ${business.name}`)\n lines.push('')\n \n // Blockquote summary (per llms.txt spec)\n const summary =\n business.tagline || business.description?.split('.')[0] || business.name\n lines.push(`> ${summary}`)\n if (meta?.last_updated) {\n lines.push(`> Content index last updated: ${meta.last_updated}`)\n }\n if (meta?.primary_language) {\n lines.push(`> Primary language: ${meta.primary_language}`)\n }\n if (meta?.llms_disclaimer) {\n lines.push(`> ${meta.llms_disclaimer}`)\n }\n \n if (business.industry) {\n lines.push('')\n lines.push(`**Industry:** ${business.industry}`)\n }\n \n if (business.service_area) {\n lines.push(`**Service Area:** ${business.service_area}`)\n }\n \n const website = business.website || resolvedBaseUrl\n if (website) {\n lines.push(`**Website:** ${website}`)\n }\n\n return lines.join('\\n')\n}\n\nfunction generateAboutSection(business: LLMBusinessInfo): string {\n const lines: string[] = []\n \n lines.push('## About')\n lines.push('')\n lines.push(business.description)\n \n if (business.founded) {\n lines.push('')\n lines.push(`Established: ${business.founded}`)\n }\n\n return lines.join('\\n')\n}\n\nfunction generateServicesSection(services: LLMService[]): string {\n const lines: string[] = []\n \n lines.push('## Services')\n lines.push('')\n \n for (const service of services) {\n if (service.url) {\n lines.push(`- **[${service.name}](${service.url})**: ${service.description}`)\n } else {\n lines.push(`- **${service.name}**: ${service.description}`)\n }\n }\n\n return lines.join('\\n')\n}\n\nfunction generatePortfolioSection(items: LLMPortfolioItem[], baseUrl: string): string {\n const lines: string[] = []\n\n lines.push('## Portfolio & Case Studies')\n lines.push('')\n\n for (const item of items) {\n const url = item.live_url || (item.slug ? `${baseUrl}/portfolio/${item.slug}` : '')\n\n if (url) {\n lines.push(`### [${item.title}](${url})`)\n } else {\n lines.push(`### ${item.title}`)\n }\n lines.push('')\n\n if (item.description) {\n lines.push(item.description)\n lines.push('')\n }\n\n const meta: string[] = []\n if (item.category) {\n meta.push(`**Category:** ${item.category}`)\n }\n if (item.services?.length) {\n meta.push(`**Services:** ${item.services.join(', ')}`)\n }\n if (item.live_url) {\n meta.push(`**Live Site:** ${item.live_url}`)\n }\n\n if (meta.length > 0) {\n lines.push(meta.join(' | '))\n lines.push('')\n }\n }\n\n return lines.join('\\n').trim()\n}\n\nfunction generateContactSection(contact: LLMContactInfo): string {\n const lines: string[] = []\n \n lines.push('## Contact Information')\n lines.push('')\n \n if (contact.phone) {\n lines.push(`- **Phone:** ${contact.phone}`)\n }\n if (contact.email) {\n lines.push(`- **Email:** ${contact.email}`)\n }\n if (contact.address || contact.city) {\n const addressParts = [\n contact.address,\n contact.city,\n contact.state,\n contact.postal_code,\n contact.country\n ].filter(Boolean)\n lines.push(`- **Address:** ${addressParts.join(', ')}`)\n }\n if (contact.hours) {\n lines.push(`- **Hours:** ${contact.hours}`)\n }\n\n return lines.join('\\n')\n}\n\nfunction generateFAQSection(faq: LLMFAQItem[]): string {\n const lines: string[] = []\n \n lines.push('## Frequently Asked Questions')\n lines.push('')\n \n for (const item of faq) {\n lines.push(`### ${item.question}`)\n lines.push('')\n lines.push(item.answer)\n lines.push('')\n }\n\n return lines.join('\\n').trim()\n}\n\nfunction pageListNote(\n page: LLMPageSummary,\n publicSummaryOnly: boolean,\n): string | undefined {\n const pub = sanitizeLlmsPublicSummary(page.llms_public_summary)\n if (pub) return pub\n if (publicSummaryOnly) return undefined\n if (page.description) return page.description.replace(/[\\[\\]\\r\\n]/g, ' ').trim()\n return undefined\n}\n\nfunction generatePagesSection(\n pages: LLMPageSummary[],\n baseUrl: string,\n publicSummaryOnly: boolean,\n): string {\n const lines: string[] = []\n \n lines.push('## Site Pages')\n lines.push('')\n \n for (const page of pages) {\n const url = page.path.startsWith('http') ? page.path : `${baseUrl}${page.path}`\n const note = pageListNote(page, publicSummaryOnly)\n if (note) {\n lines.push(`- [${page.title}](${url}): ${note}`)\n } else {\n lines.push(`- [${page.title}](${url})`)\n }\n }\n\n return lines.join('\\n')\n}\n\nfunction generateOptionalPagesSection(\n paths: string[],\n pages: LLMPageSummary[],\n baseUrl: string,\n): string | null {\n const normalizedBase = baseUrl.replace(/\\/$/, '')\n const byPath = new Map(pages.map(p => [p.path.replace(/\\/$/, '') || '/', p]))\n const lines: string[] = ['## Optional', '']\n let any = false\n for (const raw of paths) {\n const p = raw.startsWith('/') ? raw : `/${raw}`\n const norm = p.replace(/\\/$/, '') || '/'\n const match = byPath.get(norm) || byPath.get(`${norm}/`)\n const title = match?.title || norm.split('/').filter(Boolean).pop() || norm\n const url = `${normalizedBase}${p.endsWith('/') ? p : `${p}/`}`\n lines.push(`- [${title}](${url})`)\n any = true\n }\n return any ? lines.join('\\n') : null\n}\n\nfunction generateEntitySection(\n entities: SEOEntity[],\n primaryEntity: SEOEntity | null,\n detailed: boolean\n): string {\n const lines: string[] = []\n\n lines.push('## Knowledge Graph')\n lines.push('')\n\n // Primary entity first\n if (primaryEntity) {\n lines.push(`### ${primaryEntity.name} (Primary)`)\n lines.push('')\n lines.push(`- **Type:** ${primaryEntity.entity_type}`)\n if (primaryEntity.schema_type) {\n lines.push(`- **Schema:** ${primaryEntity.schema_type}`)\n }\n if (detailed && primaryEntity.knows_about?.length) {\n lines.push(`- **Knows About:** ${primaryEntity.knows_about.join(', ')}`)\n }\n if (detailed && primaryEntity.same_as?.length) {\n lines.push(`- **Same As:** ${primaryEntity.same_as.join(', ')}`)\n }\n lines.push('')\n }\n\n // Group remaining entities by type\n const grouped = new Map<string, SEOEntity[]>()\n for (const entity of entities) {\n if (primaryEntity && entity.id === primaryEntity.id) continue\n const type = entity.entity_type\n if (!grouped.has(type)) grouped.set(type, [])\n grouped.get(type)!.push(entity)\n }\n\n for (const [type, group] of grouped) {\n const label = type.charAt(0).toUpperCase() + type.slice(1) + 's'\n lines.push(`### ${label}`)\n lines.push('')\n for (const entity of group) {\n if (detailed) {\n lines.push(`- **${entity.name}**`)\n if (entity.knows_about?.length) {\n lines.push(` - Knows About: ${entity.knows_about.join(', ')}`)\n }\n if (entity.same_as?.length) {\n lines.push(` - Same As: ${entity.same_as.join(', ')}`)\n }\n } else {\n lines.push(`- ${entity.name}`)\n }\n }\n lines.push('')\n }\n\n return lines.join('\\n').trim()\n}\n\nexport default generateLLMsTxt\n","/**\n * @sonordev/site-kit/llms - Build-Time Write\n *\n * Fetches AI-optimized llms.txt from Portal API and writes to public/llms.txt\n * at build time. Integrates with sitemap flow when optimizedLLMsTxt is enabled.\n */\n\nimport { writeFileSync, mkdirSync, existsSync, renameSync, unlinkSync } from 'fs'\nimport { join } from 'path'\nimport { getOptimizedLLMsTxt } from './api'\nimport { generateLLMsTxt, generateLLMsFullTxt } from './generateLLMsTxt'\nimport type { LLMsDataResponse, LLMSTxtContent } from './types'\n\nexport interface WriteLLMsTxtOptions {\n /** Output directory (default: public, relative to cwd) */\n outputDir?: string\n /** Write llms-full.txt as well */\n full?: boolean\n /** Portal API URL */\n apiUrl?: string\n /** Portal API key */\n apiKey?: string\n /** Fallback to non-optimized when API fails */\n fallbackToLocal?: boolean\n /** When Portal returns empty services/faq/pages, use this to supply local site data */\n getLocalData?: () => Promise<LLMsDataResponse | null>\n /** Forward to GET /api/public/llms/txt and align local fallback with site-kit strict page notes */\n publicSummaryOnly?: boolean\n}\n\n/**\n * Fetch optimized llms.txt from Portal and write to public/llms.txt\n * Called at build time after sitemap sync (when optimizedLLMsTxt is enabled)\n *\n * Never persists a failure stub: when neither the Portal API nor local data\n * yields real content, the write is skipped entirely so a previously\n * generated (or committed) file keeps serving.\n */\nexport async function writeLLMsTxtToPublic(\n options: WriteLLMsTxtOptions = {}\n): Promise<{ success: boolean; path: string; optimized: boolean }> {\n const {\n outputDir = 'public',\n full = false,\n apiUrl,\n apiKey,\n fallbackToLocal = true,\n getLocalData,\n publicSummaryOnly,\n } = options\n\n const cwd = typeof process !== 'undefined' ? process.cwd() : '.'\n const outPath = join(cwd, outputDir)\n const llmsPath = join(outPath, 'llms.txt')\n const llmsFullPath = join(outPath, 'llms-full.txt')\n\n // Ensure output directory exists\n if (!existsSync(outPath)) {\n mkdirSync(outPath, { recursive: true })\n }\n\n const apiOptions = { apiUrl, apiKey, publicSummaryOnly }\n\n const genOpts = {\n getLocalData,\n pageListNotesFromPublicSummaryOnly: !!publicSummaryOnly,\n }\n\n // Fetch optimized content\n let markdown = toWritableMarkdown(await getOptimizedLLMsTxt({ ...apiOptions, full: false }))\n let optimized = !!markdown\n\n if (!markdown && fallbackToLocal) {\n console.warn('[site-kit] Optimized llms.txt unavailable, using local generation')\n const result = await generateLLMsTxt(genOpts)\n markdown = toWritableMarkdown(result.markdown, result.metadata)\n }\n\n if (!markdown) {\n console.warn(\n `[site-kit] llms.txt unavailable (Portal fetch failed, no local data) — skipped write, keeping any existing file at ${llmsPath}`\n )\n return { success: false, path: llmsPath, optimized: false }\n }\n\n atomicWriteSync(llmsPath, markdown)\n console.log(`[site-kit] Wrote llms.txt to ${llmsPath}`)\n\n if (full) {\n let fullMarkdown = toWritableMarkdown(await getOptimizedLLMsTxt({ ...apiOptions, full: true }))\n if (!fullMarkdown && fallbackToLocal) {\n const result = await generateLLMsFullTxt(genOpts)\n fullMarkdown = toWritableMarkdown(result.markdown, result.metadata)\n }\n if (fullMarkdown) {\n atomicWriteSync(llmsFullPath, fullMarkdown)\n console.log(`[site-kit] Wrote llms-full.txt to ${llmsFullPath}`)\n } else {\n console.warn(\n `[site-kit] llms-full.txt unavailable — skipped write, keeping any existing file at ${llmsFullPath}`\n )\n }\n }\n\n return { success: true, path: llmsPath, optimized }\n}\n\n/**\n * Single source of truth for \"is this real llms.txt content that may be\n * persisted?\" — applied to both the optimized Portal response and the\n * local-generation fallback (llms.txt and llms-full.txt).\n *\n * generateLLMsTxt returns an \"Information not available.\" stub with zero\n * metadata.sections when the Portal fetch and local data both fail. Stubs and\n * empty responses must never reach disk: consumer route handlers serve\n * public/llms.txt with preferStatic, so a single failed build would replace a\n * good file and keep serving the stub to AI crawlers until the next\n * successful build.\n */\nfunction toWritableMarkdown(\n markdown: string | null | undefined,\n metadata?: LLMSTxtContent['metadata'],\n): string | null {\n if (!markdown || !markdown.trim()) return null\n if (metadata && metadata.sections.length === 0) return null\n return markdown\n}\n\n/**\n * Atomic write: write to .tmp then rename (POSIX atomic).\n * Prevents corrupted files on crash or disk-full.\n */\nfunction atomicWriteSync(filePath: string, content: string): void {\n const tmp = `${filePath}.tmp`\n try {\n writeFileSync(tmp, content, 'utf-8')\n renameSync(tmp, filePath)\n } catch (err) {\n // Clean up temp file on failure\n try { unlinkSync(tmp) } catch { /* ignore */ }\n throw err\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/middleware/securityHeaders.ts"],"names":[],"mappings":";;;AA2BO,SAAS,qBACd,MAAA,EACwB;AACxB,EAAA,IAAI,MAAA,KAAW,KAAA,EAAO,OAAO,EAAC;AAE9B,EAAA,MAAM,CAAA,GACJ,OAAO,MAAA,KAAW,QAAA,GAAW,SAAS,EAAC;AAEzC,EAAA,MAAM,UAAkC,EAAC;AAGzC,EAAA,IAAI,CAAA,CAAE,uBAAuB,KAAA,EAAO;AAClC,IAAA,OAAA,CAAQ,wBAAwB,CAAA,GAAI,IAAA;AAAA,EACtC;AAGA,EAAA,IAAI,CAAA,CAAE,iBAAiB,KAAA,EAAO;AAC5B,IAAA,OAAA,CAAQ,iBAAiB,CAAA,GAAI,CAAA,CAAE,YAAA,IAAgB,MAAA;AAAA,EACjD;AAGA,EAAA,IAAI,CAAA,CAAE,uBAAuB,KAAA,EAAO;AAClC,IAAA,OAAA,CAAQ,wBAAwB,CAAA,GAAI,SAAA;AAAA,EACtC;AAGA,EAAA,IAAI,CAAA,CAAE,kBAAkB,KAAA,EAAO;AAC7B,IAAA,OAAA,CAAQ,kBAAkB,CAAA,GAAI,eAAA;AAAA,EAChC;AAGA,EAAA,OAAA,CAAQ,iBAAiB,CAAA,GACvB,CAAA,CAAE,cAAA,IAAkB,iCAAA;AAGtB,EAAA,OAAA,CAAQ,oBAAoB,CAAA,GAC1B,CAAA,CAAE,iBAAA,IAAqB,0CAAA;AAGzB,EAAA,IAAI,EAAE,aAAA,EAAe;AACnB,IAAA,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,CAAA,CAAE,aAAa,CAAA;AAAA,EACxC;AAEA,EAAA,OAAO,OAAA;AACT","file":"chunk-3MYZS6PD.js","sourcesContent":["/**\n * Default security headers applied by site-kit middleware.\n *\n * These match industry best practices and are the same headers\n * recommended by Next.js documentation. All are opt-out.\n */\n\nexport interface SecurityHeadersConfig {\n /** X-Frame-Options value. false to disable. Default: 'DENY' */\n frameOptions?: 'DENY' | 'SAMEORIGIN' | false\n /** X-Content-Type-Options: nosniff. Default: true */\n contentTypeOptions?: boolean\n /** X-XSS-Protection header. Default: true */\n xssProtection?: boolean\n /** Referrer-Policy value. Default: 'strict-origin-when-cross-origin' */\n referrerPolicy?: string\n /** Permissions-Policy value. Default restricts camera, microphone, geolocation */\n permissionsPolicy?: string\n /** X-DNS-Prefetch-Control. Default: true (on) */\n dnsPrefetchControl?: boolean\n /** Additional custom headers */\n customHeaders?: Record<string, string>\n}\n\n/**\n * Build a flat Record of header name → value from the config.\n */\nexport function buildSecurityHeaders(\n config?: SecurityHeadersConfig | boolean,\n): Record<string, string> {\n if (config === false) return {}\n\n const c: SecurityHeadersConfig =\n typeof config === 'object' ? config : {}\n\n const headers: Record<string, string> = {}\n\n // X-DNS-Prefetch-Control\n if (c.dnsPrefetchControl !== false) {\n headers['X-DNS-Prefetch-Control'] = 'on'\n }\n\n // X-Frame-Options\n if (c.frameOptions !== false) {\n headers['X-Frame-Options'] = c.frameOptions || 'DENY'\n }\n\n // X-Content-Type-Options\n if (c.contentTypeOptions !== false) {\n headers['X-Content-Type-Options'] = 'nosniff'\n }\n\n // X-XSS-Protection\n if (c.xssProtection !== false) {\n headers['X-XSS-Protection'] = '1; mode=block'\n }\n\n // Referrer-Policy\n headers['Referrer-Policy'] =\n c.referrerPolicy || 'strict-origin-when-cross-origin'\n\n // Permissions-Policy\n headers['Permissions-Policy'] =\n c.permissionsPolicy || 'camera=(), microphone=(), geolocation=()'\n\n // Custom headers\n if (c.customHeaders) {\n Object.assign(headers, c.customHeaders)\n }\n\n return headers\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/middleware/securityHeaders.ts"],"names":[],"mappings":";AA2BO,SAAS,qBACd,MAAA,EACwB;AACxB,EAAA,IAAI,MAAA,KAAW,KAAA,EAAO,OAAO,EAAC;AAE9B,EAAA,MAAM,CAAA,GACJ,OAAO,MAAA,KAAW,QAAA,GAAW,SAAS,EAAC;AAEzC,EAAA,MAAM,UAAkC,EAAC;AAGzC,EAAA,IAAI,CAAA,CAAE,uBAAuB,KAAA,EAAO;AAClC,IAAA,OAAA,CAAQ,wBAAwB,CAAA,GAAI,IAAA;AAAA,EACtC;AAGA,EAAA,IAAI,CAAA,CAAE,iBAAiB,KAAA,EAAO;AAC5B,IAAA,OAAA,CAAQ,iBAAiB,CAAA,GAAI,CAAA,CAAE,YAAA,IAAgB,MAAA;AAAA,EACjD;AAGA,EAAA,IAAI,CAAA,CAAE,uBAAuB,KAAA,EAAO;AAClC,IAAA,OAAA,CAAQ,wBAAwB,CAAA,GAAI,SAAA;AAAA,EACtC;AAGA,EAAA,IAAI,CAAA,CAAE,kBAAkB,KAAA,EAAO;AAC7B,IAAA,OAAA,CAAQ,kBAAkB,CAAA,GAAI,eAAA;AAAA,EAChC;AAGA,EAAA,OAAA,CAAQ,iBAAiB,CAAA,GACvB,CAAA,CAAE,cAAA,IAAkB,iCAAA;AAGtB,EAAA,OAAA,CAAQ,oBAAoB,CAAA,GAC1B,CAAA,CAAE,iBAAA,IAAqB,0CAAA;AAGzB,EAAA,IAAI,EAAE,aAAA,EAAe;AACnB,IAAA,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,CAAA,CAAE,aAAa,CAAA;AAAA,EACxC;AAEA,EAAA,OAAO,OAAA;AACT","file":"chunk-6BIPAKL4.mjs","sourcesContent":["/**\n * Default security headers applied by site-kit middleware.\n *\n * These match industry best practices and are the same headers\n * recommended by Next.js documentation. All are opt-out.\n */\n\nexport interface SecurityHeadersConfig {\n /** X-Frame-Options value. false to disable. Default: 'DENY' */\n frameOptions?: 'DENY' | 'SAMEORIGIN' | false\n /** X-Content-Type-Options: nosniff. Default: true */\n contentTypeOptions?: boolean\n /** X-XSS-Protection header. Default: true */\n xssProtection?: boolean\n /** Referrer-Policy value. Default: 'strict-origin-when-cross-origin' */\n referrerPolicy?: string\n /** Permissions-Policy value. Default restricts camera, microphone, geolocation */\n permissionsPolicy?: string\n /** X-DNS-Prefetch-Control. Default: true (on) */\n dnsPrefetchControl?: boolean\n /** Additional custom headers */\n customHeaders?: Record<string, string>\n}\n\n/**\n * Build a flat Record of header name → value from the config.\n */\nexport function buildSecurityHeaders(\n config?: SecurityHeadersConfig | boolean,\n): Record<string, string> {\n if (config === false) return {}\n\n const c: SecurityHeadersConfig =\n typeof config === 'object' ? config : {}\n\n const headers: Record<string, string> = {}\n\n // X-DNS-Prefetch-Control\n if (c.dnsPrefetchControl !== false) {\n headers['X-DNS-Prefetch-Control'] = 'on'\n }\n\n // X-Frame-Options\n if (c.frameOptions !== false) {\n headers['X-Frame-Options'] = c.frameOptions || 'DENY'\n }\n\n // X-Content-Type-Options\n if (c.contentTypeOptions !== false) {\n headers['X-Content-Type-Options'] = 'nosniff'\n }\n\n // X-XSS-Protection\n if (c.xssProtection !== false) {\n headers['X-XSS-Protection'] = '1; mode=block'\n }\n\n // Referrer-Policy\n headers['Referrer-Policy'] =\n c.referrerPolicy || 'strict-origin-when-cross-origin'\n\n // Permissions-Policy\n headers['Permissions-Policy'] =\n c.permissionsPolicy || 'camera=(), microphone=(), geolocation=()'\n\n // Custom headers\n if (c.customHeaders) {\n Object.assign(headers, c.customHeaders)\n }\n\n return headers\n}\n"]}