@sonordev/site-kit 8.2.0 → 8.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 (198) hide show
  1. package/AGENTS.md +13 -1
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +9 -5
  4. package/agent-manifest.json +53 -8
  5. package/dist/{AnalyticsProvider-6TAA3XYB.js → AnalyticsProvider-D6GWEJSB.js} +6 -6
  6. package/dist/{ArticleFaqSection-3Q26DP7P.js → ArticleFaqSection-DEWE5B4Q.js} +1 -1
  7. package/dist/{ArticleViewTracker-H4N7YCLC.js → ArticleViewTracker-YZ76HM64.js} +17 -6
  8. package/dist/{BlocksPopup-FJT5YQD3.js → BlocksPopup-UJXZ4AXG.js} +6 -6
  9. package/dist/{ChatWidget-THQHHTAA.js → ChatWidget-H4EOSH5I.js} +6 -6
  10. package/dist/{FileField-OZXXJGUM.js → FileField-CKBYGCNT.js} +4 -4
  11. package/dist/{FormSpotlight-MLDJS246.js → FormSpotlight-CGF5ZE6S.js} +1 -1
  12. package/dist/{FormStage-6RVY7M3R.js → FormStage-PQPUPQWW.js} +1 -1
  13. package/dist/{ManagedForm-3VV54RVH.js → ManagedForm-YOEZ7CFS.js} +7 -7
  14. package/dist/{ManagedNewsletterForm-RTJDGMGG.js → ManagedNewsletterForm-EUWJ2HCA.js} +25 -11
  15. package/dist/{SignalCore-T7ZOCA44.js → SignalCore-JZSU7A44.js} +14 -8
  16. package/dist/SiteChat-OAZH34W7.js +6 -0
  17. package/dist/SiteDesignReporter-IWBMZJYU.js +12 -0
  18. package/dist/{SitePopups-K6ADAWFK.js → SitePopups-MLAT35UN.js} +6 -6
  19. package/dist/SitemapSync-6KQLKFO2.js +9 -0
  20. package/dist/_client/booking-widget.js +6 -6
  21. package/dist/_client/testimonial-section.js +3 -3
  22. package/dist/affiliates/index.js +4 -4
  23. package/dist/analytics/index.js +6 -6
  24. package/dist/analytics/publication-cta.d.ts +3 -0
  25. package/dist/{article-styles-GFXJJDLE.js → article-styles-AOOVVKXH.js} +7 -5
  26. package/dist/article-tables-6XHVULPU.js +2 -0
  27. package/dist/articles/Article.d.ts +2 -89
  28. package/dist/articles/ArticleFAQ.d.ts +2 -41
  29. package/dist/articles/ArticleFaqSection.d.ts +2 -2
  30. package/dist/articles/ArticleList.d.ts +2 -79
  31. package/dist/articles/ArticleViewTracker.d.ts +2 -15
  32. package/dist/articles/AuthorCard.d.ts +2 -10
  33. package/dist/articles/AuthorPage.d.ts +2 -8
  34. package/dist/articles/ClusterLandingPage.d.ts +2 -40
  35. package/dist/articles/ClusterNavigation.d.ts +2 -37
  36. package/dist/articles/ManagedNewsletterForm.d.ts +3 -12
  37. package/dist/articles/NewsletterShell.d.ts +2 -17
  38. package/dist/articles/NewsletterWidget.d.ts +2 -30
  39. package/dist/articles/PublicationLayout.d.ts +2 -67
  40. package/dist/articles/PublicationSidebar.d.ts +2 -36
  41. package/dist/articles/RelatedPosts.d.ts +2 -22
  42. package/dist/articles/ServiceCallout.d.ts +2 -56
  43. package/dist/articles/TableOfContents.d.ts +2 -6
  44. package/dist/articles/article-photos.d.ts +2 -9
  45. package/dist/articles/article-styles.d.ts +2 -21
  46. package/dist/articles/article-tables.d.ts +2 -12
  47. package/dist/articles/artwork.d.ts +2 -13
  48. package/dist/articles/author-schema.d.ts +2 -72
  49. package/dist/articles/author-social.d.ts +2 -14
  50. package/dist/articles/excerpt.d.ts +2 -17
  51. package/dist/articles/index.d.ts +2 -79
  52. package/dist/articles/index.js +16 -11
  53. package/dist/articles/news-sitemap.d.ts +2 -46
  54. package/dist/articles/processArticleHtml.d.ts +2 -34
  55. package/dist/articles/public-reads.d.ts +2 -26
  56. package/dist/articles/reading-time.d.ts +2 -9
  57. package/dist/articles/routes.d.ts +2 -52
  58. package/dist/articles/server-core.d.ts +2 -461
  59. package/dist/articles/server-ui.d.ts +2 -30
  60. package/dist/articles/server-ui.js +72 -62
  61. package/dist/articles/server.d.ts +2 -461
  62. package/dist/articles/server.js +14 -5
  63. package/dist/articles/types.d.ts +2 -316
  64. package/dist/articles/widget-styles.d.ts +2 -8
  65. package/dist/chat/index.js +8 -8
  66. package/dist/chunk-34ZYJTQR.js +1 -0
  67. package/dist/{chunk-727R7C5R.js → chunk-3VSFOD2Z.js} +2 -2
  68. package/dist/{chunk-JC2VS2SB.js → chunk-44GVU5UH.js} +1 -1
  69. package/dist/{chunk-WYZ4OUON.js → chunk-4HYIDQJJ.js} +1 -1
  70. package/dist/{chunk-WMVK77ND.js → chunk-4K735O3J.js} +1 -1
  71. package/dist/{chunk-L5UOHS6E.js → chunk-5D7ZISUP.js} +1 -1
  72. package/dist/{chunk-Q72M5KBS.js → chunk-5S7YTOCB.js} +1 -1
  73. package/dist/{chunk-WSNG2K3T.js → chunk-5TDZHIG6.js} +3 -3
  74. package/dist/{chunk-6CJGZFOU.js → chunk-A4MPHIVP.js} +1 -1
  75. package/dist/chunk-B7T2SFUF.js +1 -0
  76. package/dist/{chunk-FV2VD7WM.js → chunk-BC7JMY4Z.js} +3 -3
  77. package/dist/chunk-BLCHQIWR.js +319 -0
  78. package/dist/{chunk-NNEIBXGU.js → chunk-BLENFNBW.js} +2 -2
  79. package/dist/{chunk-NFRJTOTB.js → chunk-BSQP6PRA.js} +1 -1
  80. package/dist/{chunk-GKGSXUVQ.js → chunk-BVB5FBAA.js} +1 -1
  81. package/dist/{chunk-WACWV5EP.js → chunk-CE7VPAEH.js} +3 -3
  82. package/dist/{chunk-GYF2ULVO.js → chunk-DJAYFHVF.js} +1 -1
  83. package/dist/{chunk-WBC5B3JD.js → chunk-DKKYZLKR.js} +3 -3
  84. package/dist/{chunk-CAH4Y4PY.js → chunk-DLM4FFNH.js} +6 -2
  85. package/dist/{chunk-575L73NT.js → chunk-DS6LECIX.js} +1 -1
  86. package/dist/{chunk-Y3INC4QJ.js → chunk-E4PTMORJ.js} +1 -1
  87. package/dist/chunk-H72ZFO3F.js +1 -0
  88. package/dist/{chunk-WK3N3Y7V.js → chunk-HH2GOZTO.js} +2 -2
  89. package/dist/{chunk-JBEUZJS3.js → chunk-ITY4UZEJ.js} +3 -3
  90. package/dist/{chunk-GWP2VBFH.js → chunk-J4KX2D3Q.js} +3 -3
  91. package/dist/{chunk-57K4GW3D.js → chunk-JCSU6EJI.js} +1 -1
  92. package/dist/{chunk-SC4MZGWZ.js → chunk-JHTPHA2D.js} +6 -3
  93. package/dist/{chunk-YBAFUM3Z.js → chunk-JV5YWTJN.js} +13 -4
  94. package/dist/{chunk-I6QFPSUU.js → chunk-KASKB7UK.js} +11 -10
  95. package/dist/{chunk-SMYX3AAO.js → chunk-LEGMPX6N.js} +1 -1
  96. package/dist/{chunk-ZM2FNWIQ.js → chunk-LPVEBQVL.js} +1 -1
  97. package/dist/{chunk-HUBMKTPW.js → chunk-M5SF7NCC.js} +1 -1
  98. package/dist/{chunk-EBILJHUF.js → chunk-MTV5LYXN.js} +31 -2
  99. package/dist/{chunk-5ZCY36TY.js → chunk-MZX4EN6Z.js} +1 -1
  100. package/dist/{chunk-7FSB2EXS.js → chunk-OKITZFML.js} +1 -1
  101. package/dist/{chunk-H4R2GPAB.js → chunk-PEI6DRSK.js} +2 -2
  102. package/dist/{chunk-FVXFLVXF.js → chunk-QD73RO67.js} +3 -3
  103. package/dist/{chunk-66G47P5C.js → chunk-QKOVP7WO.js} +2 -2
  104. package/dist/{chunk-3EU6S5YC.js → chunk-RBNHRZGD.js} +1 -1
  105. package/dist/{chunk-XWIRU6UT.js → chunk-S6QDNXDK.js} +2 -2
  106. package/dist/{chunk-FQUGGPBM.js → chunk-TY6WNQO3.js} +124 -41
  107. package/dist/{chunk-QXMIKDOL.js → chunk-UVYUTBT4.js} +14 -4
  108. package/dist/{chunk-3G7YABRA.js → chunk-W7OPEMGJ.js} +4 -1
  109. package/dist/{chunk-JIH32RH2.js → chunk-XA7Q2VQA.js} +1 -1
  110. package/dist/{chunk-X7VKRHFF.js → chunk-XENW66OF.js} +1 -1
  111. package/dist/chunk-XI2XM7UG.js +14 -0
  112. package/dist/{chunk-BQZPHICL.js → chunk-YM5KMNTU.js} +1 -1
  113. package/dist/client/index.js +4 -16
  114. package/dist/fleet/index.js +6 -6
  115. package/dist/forms/index.js +9 -325
  116. package/dist/forms/server.js +2 -2
  117. package/dist/forms/types.d.ts +5 -0
  118. package/dist/forms/useForm.d.ts +4 -0
  119. package/dist/images/index.js +4 -4
  120. package/dist/index.js +1 -1
  121. package/dist/layout/client.js +9 -9
  122. package/dist/layout/index.js +10 -10
  123. package/dist/llms/index.js +8 -8
  124. package/dist/maps/index.js +4 -4
  125. package/dist/mcp/sonor.d.ts +46 -3
  126. package/dist/mcp/sonor.js +51 -29
  127. package/dist/mcp/transport.d.ts +1 -1
  128. package/dist/press-kit/articles/Article.d.ts +89 -0
  129. package/dist/press-kit/articles/ArticleFAQ.d.ts +41 -0
  130. package/dist/press-kit/articles/ArticleFaqSection.d.ts +2 -0
  131. package/dist/press-kit/articles/ArticleList.d.ts +79 -0
  132. package/dist/press-kit/articles/ArticleViewTracker.d.ts +15 -0
  133. package/dist/press-kit/articles/AuthorCard.d.ts +10 -0
  134. package/dist/press-kit/articles/AuthorPage.d.ts +8 -0
  135. package/dist/press-kit/articles/ClusterLandingPage.d.ts +40 -0
  136. package/dist/press-kit/articles/ClusterNavigation.d.ts +37 -0
  137. package/dist/press-kit/articles/ManagedNewsletterForm.d.ts +12 -0
  138. package/dist/press-kit/articles/NewsletterShell.d.ts +17 -0
  139. package/dist/press-kit/articles/NewsletterWidget.d.ts +30 -0
  140. package/dist/press-kit/articles/PublicationLayout.d.ts +67 -0
  141. package/dist/press-kit/articles/PublicationSidebar.d.ts +36 -0
  142. package/dist/press-kit/articles/RelatedPosts.d.ts +22 -0
  143. package/dist/press-kit/articles/ServiceCallout.d.ts +56 -0
  144. package/dist/press-kit/articles/TableOfContents.d.ts +6 -0
  145. package/dist/press-kit/articles/article-photos.d.ts +9 -0
  146. package/dist/press-kit/articles/article-styles.d.ts +21 -0
  147. package/dist/press-kit/articles/article-tables.d.ts +12 -0
  148. package/dist/press-kit/articles/artwork.d.ts +16 -0
  149. package/dist/press-kit/articles/author-schema.d.ts +72 -0
  150. package/dist/press-kit/articles/author-social.d.ts +14 -0
  151. package/dist/press-kit/articles/excerpt.d.ts +17 -0
  152. package/dist/press-kit/articles/index.d.ts +80 -0
  153. package/dist/press-kit/articles/news-sitemap.d.ts +40 -0
  154. package/dist/press-kit/articles/processArticleHtml.d.ts +34 -0
  155. package/dist/press-kit/articles/public-reads.d.ts +42 -0
  156. package/dist/press-kit/articles/publication-definition.d.ts +41 -0
  157. package/dist/press-kit/articles/publication-reads.d.ts +54 -0
  158. package/dist/press-kit/articles/reading-time.d.ts +9 -0
  159. package/dist/press-kit/articles/routes.d.ts +52 -0
  160. package/dist/press-kit/articles/server-core.d.ts +479 -0
  161. package/dist/press-kit/articles/server-ui.d.ts +31 -0
  162. package/dist/press-kit/articles/types.d.ts +339 -0
  163. package/dist/press-kit/articles/widget-styles.d.ts +8 -0
  164. package/dist/reputation/index.js +3 -3
  165. package/dist/reputation/server.js +2 -2
  166. package/dist/revalidate/index.js +2 -2
  167. package/dist/runtime/index.js +5 -4
  168. package/dist/seo/client.js +6 -6
  169. package/dist/seo/index.js +7 -7
  170. package/dist/seo/llms.js +8 -8
  171. package/dist/seo/register-sitemap-cli.js +1 -1
  172. package/dist/seo/sitemap.js +6 -6
  173. package/dist/server/index.js +3 -2
  174. package/dist/shared/build-entries.d.ts +2 -1
  175. package/dist/shared/clientApiConfig.d.ts +2 -0
  176. package/dist/shared/import-specifiers.d.ts +1 -1
  177. package/dist/shared/index.d.ts +6 -0
  178. package/dist/shared/index.js +8 -0
  179. package/dist/shared/reporting-gate.d.ts +2 -0
  180. package/dist/shared/version.d.ts +1 -1
  181. package/dist/signal/index.js +2 -2
  182. package/dist/sitemap/index.js +6 -6
  183. package/dist/sync/index.js +6 -6
  184. package/dist/website/images.js +4 -4
  185. package/dist/website/index.js +7 -7
  186. package/dist/website/popups.js +6 -6
  187. package/dist/{writeLLMsTxt-DGKLYXIW.js → writeLLMsTxt-N4Y4YC2H.js} +5 -5
  188. package/docs/MIGRATING-TO-PRESS-KIT.md +83 -0
  189. package/docs.json +145 -29
  190. package/package.json +15 -5
  191. package/src/articles/README.md +5 -360
  192. package/src/mcp/README.md +16 -0
  193. package/src/og/README.md +1 -1
  194. package/src/runtime/README.md +4 -0
  195. package/dist/SiteChat-JSHPGAE3.js +0 -6
  196. package/dist/SiteDesignReporter-L2JBAKKK.js +0 -12
  197. package/dist/SitemapSync-VV2YSMIW.js +0 -9
  198. package/dist/article-tables-AXSZOGNW.js +0 -2
@@ -0,0 +1,479 @@
1
+ /**
2
+ * @sonordev/press-kit/articles/server
3
+ *
4
+ * Data and metadata helpers only (no React components). For `Article` / `ArticleList`
5
+ * in the App Router, import from `@sonordev/press-kit/articles/server-ui` so Next never
6
+ * treats `getAllArticleSlugs` / `generateArticleStaticParams` as client code.
7
+ */
8
+ import type { Metadata } from 'next';
9
+ import type { Article as ArticleRecord, ArticleAuthor, TopicCluster, ClusterNavigation } from './types';
10
+ import { ArticleUnavailableError } from './public-reads';
11
+ import { sanitizeExcerpt } from './excerpt';
12
+ import { articleImageSchema, resolveRepresentativeImage } from './artwork';
13
+ import { type PublicationRoutingOptions } from './routes';
14
+ import { type NewsSitemapOptions } from './news-sitemap';
15
+ export { sanitizeExcerpt, ArticleUnavailableError, resolveRepresentativeImage, articleImageSchema };
16
+ export type { ArticleReadResult } from './public-reads';
17
+ export declare function getArticleResult(slug: string, options?: {
18
+ site?: string;
19
+ }): Promise<{
20
+ state: 'ready';
21
+ value: ArticleRecord;
22
+ } | {
23
+ state: 'not_found';
24
+ } | {
25
+ state: 'unavailable';
26
+ status?: number;
27
+ } | {
28
+ state: 'unavailable';
29
+ }>;
30
+ export declare const SEO_LIMITS: {
31
+ readonly title: {
32
+ readonly min: 30;
33
+ readonly max: 60;
34
+ readonly recommended: 55;
35
+ };
36
+ readonly metaDescription: {
37
+ readonly min: 120;
38
+ readonly max: 160;
39
+ readonly recommended: 155;
40
+ };
41
+ readonly excerpt: {
42
+ readonly min: 100;
43
+ readonly max: 300;
44
+ readonly recommended: 200;
45
+ };
46
+ readonly slug: {
47
+ readonly max: 75;
48
+ };
49
+ readonly focusKeyphrase: {
50
+ readonly min: 2;
51
+ readonly max: 4;
52
+ readonly words: true;
53
+ };
54
+ };
55
+ export interface SeoValidationResult {
56
+ field: string;
57
+ value: string;
58
+ length: number;
59
+ limit: {
60
+ min?: number;
61
+ max: number;
62
+ recommended?: number;
63
+ };
64
+ status: 'good' | 'warning' | 'error';
65
+ message: string;
66
+ }
67
+ /**
68
+ * Validate SEO title (60 chars max, keyword-first recommended)
69
+ */
70
+ export declare function validateSeoTitle(title: string, focusKeyphrase?: string): SeoValidationResult;
71
+ /**
72
+ * Validate meta description (150-160 chars, benefit-driven)
73
+ */
74
+ export declare function validateMetaDescription(description: string, focusKeyphrase?: string): SeoValidationResult;
75
+ /**
76
+ * Full SEO validation for an article
77
+ */
78
+ export declare function validateArticleSeo(post: Partial<ArticleRecord>): SeoValidationResult[];
79
+ /**
80
+ * Fetch an article by slug (server-side)
81
+ *
82
+ * @param options.site - Sub-site host override. Omit to resolve from
83
+ * NEXT_PUBLIC_SITE_URL.
84
+ */
85
+ export declare function getArticle(slug: string, options?: {
86
+ site?: string;
87
+ }): Promise<ArticleRecord | null>;
88
+ /**
89
+ * Fetch an article by slug, or answer 404 when there isn't one.
90
+ *
91
+ * `getArticle` returns null for a mistyped or deleted slug, and the page
92
+ * used to carry on rendering a "not found" message with HTTP 200 and an
93
+ * indexable title: a soft 404 on every bad post URL. This calls Next's
94
+ * `notFound()` instead, so the
95
+ * route answers 404 with `noindex`.
96
+ *
97
+ * Call it from `generateMetadata` (or the page) before rendering `Article`:
98
+ * metadata resolves before anything streams, so the status is a real 404.
99
+ * The fetch is the same one `Article` and `generateArticleMetadata` make,
100
+ * and Next dedupes it within the render.
101
+ *
102
+ * @example
103
+ * ```tsx
104
+ * export async function generateMetadata({ params }) {
105
+ * const { slug } = await params
106
+ * await requireArticle(slug)
107
+ * return generateArticleMetadata(slug, { siteName: 'Acme' })
108
+ * }
109
+ * ```
110
+ */
111
+ export declare function requireArticle(slug: string, options?: {
112
+ site?: string;
113
+ }): Promise<ArticleRecord>;
114
+ /**
115
+ * Fetch all article slugs for static generation
116
+ */
117
+ export declare function getAllArticleSlugs(): Promise<{
118
+ slug: string;
119
+ id?: string;
120
+ last_modified?: string;
121
+ article_type?: string;
122
+ }[]>;
123
+ /**
124
+ * Fetch article categories
125
+ */
126
+ export declare function getArticleCategories(options?: {
127
+ site?: string;
128
+ }): Promise<{
129
+ name: string;
130
+ slug: string;
131
+ post_count: number;
132
+ }[]>;
133
+ export interface PublicationMetadataOptions extends PublicationRoutingOptions {
134
+ /** Site name for og:site_name */
135
+ siteName?: string;
136
+ /** Base URL of the site */
137
+ siteUrl?: string;
138
+ /** URL path prefix for publication index and posts (default `/article`, e.g. `/insights`) */
139
+ /** Default OG image */
140
+ defaultImage?: string;
141
+ /** Twitter handle */
142
+ twitterHandle?: string;
143
+ }
144
+ export interface ArticleMetadataOptions extends PublicationMetadataOptions {
145
+ /**
146
+ * Declare the featured image (or `defaultImage`) as `openGraph.images` and
147
+ * `twitter.images`. Default true.
148
+ *
149
+ * Pass false when the post route has its own card, an
150
+ * `opengraph-image.tsx` beside the page. Next lets declared images beat
151
+ * that file, so leaving them in silently swaps the post's card for the raw
152
+ * photo. With false the `images` keys are left out entirely, not set to
153
+ * undefined: Next checks `hasOwnProperty('images')`, so even an undefined
154
+ * value hides the card.
155
+ */
156
+ images?: boolean;
157
+ /**
158
+ * What to do when the post doesn't exist. Default true: call Next's
159
+ * `notFound()`, so the route answers 404. False returns placeholder
160
+ * metadata marked `noindex` instead, for a page that renders its own
161
+ * missing-post state.
162
+ */
163
+ notFound?: boolean;
164
+ }
165
+ /**
166
+ * Generate metadata for an article page
167
+ */
168
+ export declare function generateArticleMetadata(slug: string, options?: ArticleMetadataOptions): Promise<Metadata>;
169
+ /**
170
+ * Generate metadata for the publication index page
171
+ */
172
+ export declare function generatePublicationMetadata(options: PublicationMetadataOptions & {
173
+ title?: string;
174
+ description?: string;
175
+ }): Metadata;
176
+ /**
177
+ * Generate metadata for a category page
178
+ */
179
+ export declare function generateArticleCategoryMetadata(categoryName: string, options?: PublicationMetadataOptions & {
180
+ categorySlug?: string;
181
+ }): Metadata;
182
+ /**
183
+ * What Next passes to a route's `generateStaticParams`: the parent segments'
184
+ * params. The publication helpers ignore it; it's typed so they can be exported
185
+ * directly as `generateStaticParams`.
186
+ */
187
+ export interface NextStaticParamsProps {
188
+ params: unknown;
189
+ }
190
+ /**
191
+ * Generate static params for article pages.
192
+ *
193
+ * Export it directly for the default `/article/[slug]` routes:
194
+ *
195
+ * export const generateStaticParams = generateArticleStaticParams
196
+ *
197
+ * With routing options, wrap it:
198
+ *
199
+ * export function generateStaticParams() {
200
+ * return generateArticleStaticParams(routing)
201
+ * }
202
+ */
203
+ export declare function generateArticleStaticParams(options?: PublicationRoutingOptions): Promise<{
204
+ slug: string;
205
+ category?: string;
206
+ }[]>;
207
+ export declare function generateArticleStaticParams(props: NextStaticParamsProps): Promise<{
208
+ slug: string;
209
+ category?: string;
210
+ }[]>;
211
+ /**
212
+ * Generate static params for category pages. Takes no arguments, so it can be
213
+ * exported directly:
214
+ *
215
+ * export const generateStaticParams = generateCategoryStaticParams
216
+ */
217
+ export declare function generateCategoryStaticParams(): Promise<{
218
+ category: string;
219
+ }[]>;
220
+ interface SitemapEntry {
221
+ url: string;
222
+ lastModified?: Date;
223
+ changeFrequency?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
224
+ priority?: number;
225
+ /** Image sitemap entries; Next's MetadataRoute.Sitemap renders them as <image:image>. */
226
+ images?: string[];
227
+ }
228
+ /**
229
+ * Generate sitemap entries for articles
230
+ */
231
+ export interface ArticleSitemapOptions extends PublicationRoutingOptions {
232
+ includeCategories?: boolean;
233
+ includeClusters?: boolean;
234
+ }
235
+ export declare function generateArticleSitemap(siteUrl: string, options?: ArticleSitemapOptions): Promise<SitemapEntry[]>;
236
+ /**
237
+ * Google News sitemap XML for posts published in the last two days. Serve it
238
+ * from a route (app/news-sitemap.xml/route.ts) and list it in robots.txt.
239
+ */
240
+ export declare function generateNewsSitemap(options: NewsSitemapOptions & {
241
+ site?: string;
242
+ }): Promise<string>;
243
+ /**
244
+ * Generate JSON-LD schema for an article
245
+ */
246
+ export declare function generateArticleSchema(post: ArticleRecord, options?: PublicationRoutingOptions & {
247
+ siteUrl?: string;
248
+ siteName?: string;
249
+ logoUrl?: string;
250
+ }): object;
251
+ /**
252
+ * Generate JSON-LD schema for publication index/listing page
253
+ */
254
+ export declare function generateArticleListSchema(options?: PublicationRoutingOptions & {
255
+ siteUrl?: string;
256
+ siteName?: string;
257
+ description?: string;
258
+ }): object;
259
+ /**
260
+ * Generate standalone FAQ schema (great for PAA inclusion)
261
+ */
262
+ export declare function generateFaqSchema(faqItems: {
263
+ question: string;
264
+ answer: string;
265
+ }[]): object | null;
266
+ export interface HowToStep {
267
+ name: string;
268
+ text: string;
269
+ image?: string;
270
+ url?: string;
271
+ }
272
+ /**
273
+ * Generate HowTo schema for step-by-step posts
274
+ */
275
+ export declare function generateHowToSchema(post: ArticleRecord, steps: HowToStep[], options?: PublicationRoutingOptions & {
276
+ siteUrl?: string;
277
+ }): object;
278
+ export interface RssFeedOptions extends PublicationRoutingOptions {
279
+ siteUrl: string;
280
+ siteName: string;
281
+ description?: string;
282
+ language?: string;
283
+ copyright?: string;
284
+ managingEditor?: string;
285
+ webMaster?: string;
286
+ ttl?: number;
287
+ imageUrl?: string;
288
+ /** Most recent posts to include. Defaults to FEED_DEFAULT_ITEMS (20); older posts stay in the sitemap. */
289
+ maxItems?: number;
290
+ }
291
+ /**
292
+ * Fetch all published articles for RSS feed.
293
+ *
294
+ * Paginates with `per_page`/`page` — the only pagination params the deployed
295
+ * controller reads — accumulating up to FEED_MAX_POSTS. A mid-loop failure throws ArticleUnavailableError; a truncated archive must
296
+ * not be reported as a complete collection.
297
+ */
298
+ export declare function getAllArticles(options?: {
299
+ maxPosts?: number; /** Sub-site host override (see getArticle). */
300
+ site?: string;
301
+ }): Promise<ArticleRecord[]>;
302
+ /**
303
+ * Generate RSS 2.0 feed XML
304
+ */
305
+ export declare function generateRssFeed(options: RssFeedOptions): Promise<string>;
306
+ /**
307
+ * Generate Atom feed XML
308
+ */
309
+ export declare function generateAtomFeed(options: RssFeedOptions): Promise<string>;
310
+ /**
311
+ * Fetch all active topic clusters for the project.
312
+ * Uses the real cluster data from Sonor API (not heuristic-based).
313
+ */
314
+ export declare function getTopicClusters(options?: {
315
+ site?: string;
316
+ }): Promise<TopicCluster[]>;
317
+ /**
318
+ * Fetch a single topic cluster with its pillar and support articles.
319
+ */
320
+ export declare function getTopicCluster(slug: string, options?: {
321
+ site?: string;
322
+ }): Promise<TopicCluster | null>;
323
+ /**
324
+ * Get cluster navigation context for an article.
325
+ * Returns the cluster name, pillar link, and sibling articles.
326
+ */
327
+ export declare function getClusterNavigation(post: ArticleRecord): ClusterNavigation | null;
328
+ /**
329
+ * Fetch posts by category for topic cluster organization
330
+ */
331
+ export declare function getPostsByCategory(categorySlug: string, options?: {
332
+ site?: string;
333
+ }): Promise<ArticleRecord[]>;
334
+ /**
335
+ * Generate ItemList schema for a cluster's pillar page.
336
+ * Wraps supporting posts as a structured list Google can parse.
337
+ */
338
+ export declare function generateClusterItemListSchema(cluster: TopicCluster, options?: PublicationRoutingOptions & {
339
+ siteUrl?: string;
340
+ }): object;
341
+ /**
342
+ * Generate Article schema with cluster relationship (isPartOf / hasPart).
343
+ * - Support articles get `isPartOf` pointing to the pillar.
344
+ * - Pillar articles get `hasPart` listing all supports.
345
+ */
346
+ export declare function generateClusterArticleSchema(post: ArticleRecord, cluster: TopicCluster, options?: PublicationRoutingOptions & {
347
+ siteUrl?: string;
348
+ siteName?: string;
349
+ logoUrl?: string;
350
+ }): object;
351
+ /**
352
+ * Generate BreadcrumbList schema for a cluster-linked post.
353
+ * Path: Home > Article > Cluster > Article
354
+ */
355
+ export declare function generateClusterBreadcrumbSchema(post: ArticleRecord, cluster: TopicCluster, options?: PublicationRoutingOptions & {
356
+ siteUrl?: string;
357
+ siteName?: string;
358
+ }): object;
359
+ /**
360
+ * Generate CollectionPage schema for a cluster landing page.
361
+ */
362
+ export declare function generateClusterLandingSchema(cluster: TopicCluster, options?: PublicationRoutingOptions & {
363
+ siteUrl?: string;
364
+ siteName?: string;
365
+ }): object;
366
+ /**
367
+ * Generate metadata for a cluster landing page (Next.js generateMetadata).
368
+ */
369
+ export declare function generateClusterPageMetadata(clusterSlug: string, options?: PublicationRoutingOptions & {
370
+ siteName?: string;
371
+ siteUrl?: string;
372
+ }): Promise<{
373
+ title?: undefined;
374
+ description?: undefined;
375
+ openGraph?: undefined;
376
+ } | {
377
+ title: string;
378
+ description: string;
379
+ openGraph: {
380
+ title: string;
381
+ description: string;
382
+ url: string;
383
+ type: string;
384
+ };
385
+ }>;
386
+ /**
387
+ * Generate "Related Insights" section data
388
+ */
389
+ export declare function getRelatedInsights(currentSlug: string, options?: {
390
+ limit?: number;
391
+ category?: string; /** Sub-site host override (see getArticle). */
392
+ site?: string;
393
+ }): Promise<ArticleRecord[]>;
394
+ /**
395
+ * Generate BreadcrumbList schema for article navigation
396
+ */
397
+ export declare function generateBreadcrumbSchema(post: ArticleRecord, options?: PublicationRoutingOptions & {
398
+ siteUrl?: string;
399
+ siteName?: string;
400
+ }): object;
401
+ /**
402
+ * Generate all relevant schemas for an article in a single array
403
+ * This is the recommended way to include multiple schemas.
404
+ * When post has E-E-A-T schema (post.schema), use it instead of generating Article/FAQ.
405
+ */
406
+ export declare function generateAllArticleSchemas(post: ArticleRecord, options?: PublicationRoutingOptions & {
407
+ siteUrl?: string;
408
+ siteName?: string;
409
+ logoUrl?: string;
410
+ }): object[];
411
+ /**
412
+ * Fetch a single author by slug
413
+ */
414
+ export declare function getAuthorBySlug(slug: string, options?: {
415
+ site?: string;
416
+ }): Promise<ArticleAuthor | null>;
417
+ /**
418
+ * Fetch an author's posts by slug.
419
+ *
420
+ * `offset` pages through the controller's existing offset support. Older API
421
+ * versions return a stripped `{name, slug}` author on this endpoint; when
422
+ * that shape is detected the full author row is hydrated via getAuthorBySlug
423
+ * (both fetches revalidate:60, so the extra hop is cached and disappears once
424
+ * the API returns the full row itself).
425
+ */
426
+ export declare function getAuthorPosts(slug: string, limit?: number, offset?: number, options?: {
427
+ site?: string;
428
+ }): Promise<{
429
+ author: ArticleAuthor | null;
430
+ posts: ArticleRecord[];
431
+ total: number;
432
+ }>;
433
+ /**
434
+ * Fetch all author slugs for static generation
435
+ */
436
+ export declare function getAllAuthorSlugs(): Promise<{
437
+ slug: string;
438
+ }[]>;
439
+ /**
440
+ * Generate static params for author pages. Takes no arguments, so it can be
441
+ * exported directly:
442
+ *
443
+ * export const generateStaticParams = generateAuthorStaticParams
444
+ */
445
+ export declare function generateAuthorStaticParams(): Promise<{
446
+ slug: string;
447
+ }[]>;
448
+ /**
449
+ * Generate Next.js Metadata for an author page
450
+ */
451
+ export declare function generateAuthorPageMetadata(author: ArticleAuthor, options?: PublicationRoutingOptions & {
452
+ siteUrl?: string;
453
+ siteName?: string;
454
+ }): Metadata;
455
+ /**
456
+ * Author JSON-LD: `generateAuthorSchema` (the author page's ProfilePage with
457
+ * the Person as mainEntity), `generateAuthorPersonSchema` (the bare Person for
458
+ * embedding), `generateArticleAuthorNode` (an article byline) and
459
+ * `authorEntityId` (the Person @id rule).
460
+ *
461
+ * The implementation lives in `./author-schema` because it is pure, and
462
+ * `AuthorPage` — which is exported from the client-stamped `articles` barrel —
463
+ * needs it. Importing it from here instead would drag this entire server module
464
+ * into the browser bundle. Re-exported so `@sonordev/press-kit/articles/server`
465
+ * keeps its existing public API.
466
+ */
467
+ export { authorEntityId, generateArticleAuthorNode, generateAuthorPersonSchema, generateAuthorSchema, withArticleAuthorIdentity, type AuthorSchemaOptions, } from './author-schema';
468
+ /** Sonor article document shape (alias of `Article` from `./types`) */
469
+ export type { Article as ArticleRecord } from './types';
470
+ export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolvePublicationUrl } from './routes';
471
+ export type { ArticleRoutePost, PublicationRoutingOptions } from './routes';
472
+ export { resolveArticleArtwork } from './artwork';
473
+ export { wrapArticleTables, articleTableCss } from './article-tables';
474
+ export { insertArticlePhotos, articlePhotoCss } from './article-photos';
475
+ export type { ArticleEditorialPhoto } from './types';
476
+ export { FEED_DEFAULT_ITEMS, NEWS_SITEMAP_MAX_URLS, NEWS_SITEMAP_WINDOW_MS, buildNewsSitemapXml, cdata, recentNewsPosts } from './news-sitemap';
477
+ export type { NewsSitemapOptions, NewsSitemapPost } from './news-sitemap';
478
+ export { getPublicationIssues, getPublicationIssue, getArticlePreview, createPublicationPreviewHandler, PUBLICATION_PREVIEW_COOKIE, PUBLICATION_PREVIEW_HEADERS } from './publication-reads';
479
+ export type { PublicationIssue, PublicationIssueList, ArticlePreview } from './publication-reads';
@@ -0,0 +1,31 @@
1
+ import 'server-only';
2
+ /**
3
+ * @sonordev/press-kit/articles/server-ui
4
+ *
5
+ * RSC-safe `Article` and `ArticleList` without sharing a bundle with `articles/server`
6
+ * data helpers. Importing them from `articles/server` pulled hook-heavy chunks that
7
+ * received a synthetic `'use client'` during the site-kit build, which broke
8
+ * `generateStaticParams` and other server-only callers.
9
+ *
10
+ * Use `@sonordev/press-kit/articles/server` for getArticle, getAllArticleSlugs,
11
+ * metadata, RSS, etc.
12
+ */
13
+ export { Article } from './Article';
14
+ export type { ArticleServerProps, ArticleStyles } from './Article';
15
+ export { ArticleList } from './ArticleList';
16
+ export type { ArticleListServerProps, ArticleListStyles } from './ArticleList';
17
+ export { ClusterLandingPage } from './ClusterLandingPage';
18
+ export type { ClusterLandingPageProps } from './ClusterLandingPage';
19
+ export { ClusterNavigation } from './ClusterNavigation';
20
+ export type { ClusterNavigationProps } from './ClusterNavigation';
21
+ export { PublicationLayout, PublicationPage, ArticlePage, CategoryPage } from './PublicationLayout';
22
+ export type { PublicationLayoutProps, PublicationPageProps, ArticlePageProps, CategoryPageProps, } from './PublicationLayout';
23
+ export { PublicationSidebar } from './PublicationSidebar';
24
+ export type { PublicationSidebarProps } from './PublicationSidebar';
25
+ export { RelatedPosts } from './RelatedPosts';
26
+ export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolvePublicationUrl } from './routes';
27
+ export type { ArticleRoutePost, PublicationRoutingOptions } from './routes';
28
+ export { resolveArticleArtwork } from './artwork';
29
+ export { wrapArticleTables, articleTableCss } from './article-tables';
30
+ export { insertArticlePhotos, articlePhotoCss } from './article-photos';
31
+ export type { ArticleEditorialPhoto } from './types';