@sonordev/site-kit 8.1.0 → 8.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/AGENTS.md +13 -1
  2. package/CHANGELOG.md +11 -0
  3. package/README.md +9 -5
  4. package/agent-manifest.json +47 -8
  5. package/dist/{AnalyticsProvider-UWTCE5UO.js → AnalyticsProvider-QXO33JUF.js} +6 -6
  6. package/dist/{ArticleFaqSection-3Q26DP7P.js → ArticleFaqSection-DEWE5B4Q.js} +1 -1
  7. package/dist/{ArticleViewTracker-MYD6SGNH.js → ArticleViewTracker-KN6ENIRS.js} +17 -6
  8. package/dist/{BlocksPopup-OY5G3EFH.js → BlocksPopup-3RPN6YVJ.js} +6 -6
  9. package/dist/{ChatWidget-BTR5VERC.js → ChatWidget-D2X445PO.js} +6 -6
  10. package/dist/{FileField-DEHVYXAO.js → FileField-UNGSNGJ5.js} +4 -4
  11. package/dist/{FormSpotlight-VGC4CZL4.js → FormSpotlight-JFH2ENKQ.js} +1 -1
  12. package/dist/{FormStage-CJUSCSAL.js → FormStage-RC3WHHXP.js} +1 -1
  13. package/dist/{ManagedForm-JCI2KPMO.js → ManagedForm-FOQZ2IYG.js} +7 -7
  14. package/dist/{ManagedNewsletterForm-DTE4KKXV.js → ManagedNewsletterForm-NFNF33V3.js} +16 -7
  15. package/dist/{SignalCore-LGCBQDEH.js → SignalCore-5KABGX5C.js} +4 -4
  16. package/dist/SiteChat-JQ46ZIJ4.js +6 -0
  17. package/dist/SiteDesignReporter-N7L6DR4J.js +12 -0
  18. package/dist/{SitePopups-T6YPHAVY.js → SitePopups-WZBKX5Q3.js} +6 -6
  19. package/dist/SitemapSync-GY6UADRI.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/{article-styles-GGZOQG5X.js → article-styles-7QONZJR5.js} +3 -3
  25. package/dist/article-tables-6XHVULPU.js +2 -0
  26. package/dist/articles/Article.d.ts +2 -89
  27. package/dist/articles/ArticleFAQ.d.ts +2 -41
  28. package/dist/articles/ArticleFaqSection.d.ts +2 -2
  29. package/dist/articles/ArticleList.d.ts +2 -79
  30. package/dist/articles/ArticleViewTracker.d.ts +2 -15
  31. package/dist/articles/AuthorCard.d.ts +2 -10
  32. package/dist/articles/AuthorPage.d.ts +2 -8
  33. package/dist/articles/ClusterLandingPage.d.ts +2 -40
  34. package/dist/articles/ClusterNavigation.d.ts +2 -37
  35. package/dist/articles/ManagedNewsletterForm.d.ts +3 -12
  36. package/dist/articles/NewsletterShell.d.ts +2 -17
  37. package/dist/articles/NewsletterWidget.d.ts +2 -30
  38. package/dist/articles/PublicationLayout.d.ts +2 -67
  39. package/dist/articles/PublicationSidebar.d.ts +2 -36
  40. package/dist/articles/RelatedPosts.d.ts +2 -22
  41. package/dist/articles/ServiceCallout.d.ts +2 -56
  42. package/dist/articles/TableOfContents.d.ts +2 -6
  43. package/dist/articles/article-photos.d.ts +2 -9
  44. package/dist/articles/article-styles.d.ts +2 -21
  45. package/dist/articles/article-tables.d.ts +2 -12
  46. package/dist/articles/artwork.d.ts +2 -13
  47. package/dist/articles/author-schema.d.ts +2 -72
  48. package/dist/articles/author-social.d.ts +2 -14
  49. package/dist/articles/excerpt.d.ts +2 -17
  50. package/dist/articles/index.d.ts +2 -79
  51. package/dist/articles/index.js +16 -11
  52. package/dist/articles/news-sitemap.d.ts +2 -46
  53. package/dist/articles/processArticleHtml.d.ts +2 -34
  54. package/dist/articles/public-reads.d.ts +2 -26
  55. package/dist/articles/reading-time.d.ts +2 -9
  56. package/dist/articles/routes.d.ts +2 -52
  57. package/dist/articles/server-core.d.ts +2 -461
  58. package/dist/articles/server-ui.d.ts +2 -30
  59. package/dist/articles/server-ui.js +26 -17
  60. package/dist/articles/server.d.ts +2 -461
  61. package/dist/articles/server.js +14 -5
  62. package/dist/articles/types.d.ts +2 -315
  63. package/dist/articles/widget-styles.d.ts +2 -8
  64. package/dist/chat/index.js +8 -8
  65. package/dist/{chunk-AIDIEVPZ.js → chunk-2JMCBJM5.js} +1 -1
  66. package/dist/chunk-34ZYJTQR.js +1 -0
  67. package/dist/{chunk-ADI6IYFH.js → chunk-3OY52UFM.js} +1 -1
  68. package/dist/{chunk-WMVK77ND.js → chunk-4K735O3J.js} +1 -1
  69. package/dist/{chunk-55GHBRCN.js → chunk-4PVMUPC6.js} +2 -2
  70. package/dist/{chunk-L5UOHS6E.js → chunk-5D7ZISUP.js} +1 -1
  71. package/dist/{chunk-JT52KYHQ.js → chunk-5RYSTKVU.js} +1 -1
  72. package/dist/{chunk-6CJGZFOU.js → chunk-A4MPHIVP.js} +1 -1
  73. package/dist/chunk-B7T2SFUF.js +1 -0
  74. package/dist/{chunk-FV2VD7WM.js → chunk-BC7JMY4Z.js} +3 -3
  75. package/dist/{chunk-255NCCPB.js → chunk-BOCYBDKV.js} +1 -1
  76. package/dist/{chunk-NFRJTOTB.js → chunk-BSQP6PRA.js} +1 -1
  77. package/dist/{chunk-GKGSXUVQ.js → chunk-BVB5FBAA.js} +1 -1
  78. package/dist/{chunk-NWVB75ER.js → chunk-C2UROFGZ.js} +1 -1
  79. package/dist/{chunk-F2VYN3QL.js → chunk-C4AFNZT2.js} +1 -1
  80. package/dist/{chunk-GC2QWXJ3.js → chunk-D6ZIQMHB.js} +3 -3
  81. package/dist/{chunk-GYF2ULVO.js → chunk-DJAYFHVF.js} +1 -1
  82. package/dist/{chunk-XUCU3LX4.js → chunk-DPSNMOMZ.js} +1 -1
  83. package/dist/{chunk-A3EU6HB5.js → chunk-E3UR37RX.js} +2 -2
  84. package/dist/{chunk-Y3INC4QJ.js → chunk-E4PTMORJ.js} +1 -1
  85. package/dist/{chunk-TAO6BVA2.js → chunk-EA6FZMYA.js} +2 -2
  86. package/dist/{chunk-V56RZH7J.js → chunk-FHUTOXS7.js} +1 -1
  87. package/dist/{chunk-LLW5HKEE.js → chunk-GKJVSZ7H.js} +3 -3
  88. package/dist/chunk-H72ZFO3F.js +1 -0
  89. package/dist/{chunk-CSTC6HZO.js → chunk-HND6BDXC.js} +3 -3
  90. package/dist/chunk-IEGDPRQB.js +14 -0
  91. package/dist/{chunk-CAH4Y4PY.js → chunk-JO76F5WP.js} +1 -1
  92. package/dist/{chunk-4Z3DI2EL.js → chunk-KJVUOJMW.js} +58 -58
  93. package/dist/{chunk-SC4MZGWZ.js → chunk-LBDWAXAO.js} +1 -1
  94. package/dist/{chunk-RSBMQFZW.js → chunk-LPKKSYKX.js} +3 -3
  95. package/dist/{chunk-2UO4HPGE.js → chunk-M5SF7NCC.js} +73 -51
  96. package/dist/{chunk-S6IGQYHW.js → chunk-MQ4REMTH.js} +2 -2
  97. package/dist/{chunk-O4DETQJI.js → chunk-NA4Z4CQG.js} +1 -1
  98. package/dist/{chunk-WPOFTCKL.js → chunk-OIWFXUVD.js} +2 -2
  99. package/dist/{chunk-G2HCCWZQ.js → chunk-QBCWVT2S.js} +2 -2
  100. package/dist/{chunk-DZV3KPVF.js → chunk-QCZHYO5M.js} +1 -1
  101. package/dist/{chunk-DOMBP3FW.js → chunk-QDILCQBL.js} +9 -9
  102. package/dist/{chunk-IAYGTQJD.js → chunk-SCTVADDL.js} +2 -2
  103. package/dist/{chunk-QXMIKDOL.js → chunk-SNRE3ZVZ.js} +3 -3
  104. package/dist/{chunk-DSNCU2E3.js → chunk-TT4JZDKM.js} +3 -3
  105. package/dist/{chunk-6VHDCJIZ.js → chunk-U7Y3QG3A.js} +1 -1
  106. package/dist/{chunk-3G7YABRA.js → chunk-W7OPEMGJ.js} +4 -1
  107. package/dist/{chunk-2JEUDTL6.js → chunk-WBUG7XRL.js} +2 -2
  108. package/dist/{chunk-47VB5INH.js → chunk-WSOZ3FQN.js} +1 -1
  109. package/dist/chunk-X4IJS7LV.js +319 -0
  110. package/dist/{chunk-JIH32RH2.js → chunk-XA7Q2VQA.js} +1 -1
  111. package/dist/{chunk-5L467Z5Q.js → chunk-XLAXYPTK.js} +3 -3
  112. package/dist/client/index.js +4 -16
  113. package/dist/contracts/editorial-media.d.ts +39 -0
  114. package/dist/contracts/entries.d.ts +1 -1
  115. package/dist/fleet/index.js +6 -6
  116. package/dist/forms/index.js +9 -325
  117. package/dist/forms/server.js +2 -2
  118. package/dist/images/index.js +4 -4
  119. package/dist/index.js +1 -1
  120. package/dist/layout/client.js +9 -9
  121. package/dist/layout/index.js +10 -10
  122. package/dist/llms/index.js +8 -8
  123. package/dist/maps/index.js +4 -4
  124. package/dist/mcp/sonor.d.ts +42 -3
  125. package/dist/mcp/sonor.js +25 -20
  126. package/dist/mcp/transport.d.ts +1 -1
  127. package/dist/press-kit/articles/Article.d.ts +89 -0
  128. package/dist/press-kit/articles/ArticleFAQ.d.ts +41 -0
  129. package/dist/press-kit/articles/ArticleFaqSection.d.ts +2 -0
  130. package/dist/press-kit/articles/ArticleList.d.ts +79 -0
  131. package/dist/press-kit/articles/ArticleViewTracker.d.ts +15 -0
  132. package/dist/press-kit/articles/AuthorCard.d.ts +10 -0
  133. package/dist/press-kit/articles/AuthorPage.d.ts +8 -0
  134. package/dist/press-kit/articles/ClusterLandingPage.d.ts +40 -0
  135. package/dist/press-kit/articles/ClusterNavigation.d.ts +37 -0
  136. package/dist/press-kit/articles/ManagedNewsletterForm.d.ts +12 -0
  137. package/dist/press-kit/articles/NewsletterShell.d.ts +17 -0
  138. package/dist/press-kit/articles/NewsletterWidget.d.ts +30 -0
  139. package/dist/press-kit/articles/PublicationLayout.d.ts +67 -0
  140. package/dist/press-kit/articles/PublicationSidebar.d.ts +36 -0
  141. package/dist/press-kit/articles/RelatedPosts.d.ts +22 -0
  142. package/dist/press-kit/articles/ServiceCallout.d.ts +56 -0
  143. package/dist/press-kit/articles/TableOfContents.d.ts +6 -0
  144. package/dist/press-kit/articles/article-photos.d.ts +9 -0
  145. package/dist/press-kit/articles/article-styles.d.ts +21 -0
  146. package/dist/press-kit/articles/article-tables.d.ts +12 -0
  147. package/dist/press-kit/articles/artwork.d.ts +13 -0
  148. package/dist/press-kit/articles/author-schema.d.ts +72 -0
  149. package/dist/press-kit/articles/author-social.d.ts +14 -0
  150. package/dist/press-kit/articles/excerpt.d.ts +17 -0
  151. package/dist/press-kit/articles/index.d.ts +79 -0
  152. package/dist/press-kit/articles/news-sitemap.d.ts +46 -0
  153. package/dist/press-kit/articles/processArticleHtml.d.ts +34 -0
  154. package/dist/press-kit/articles/public-reads.d.ts +26 -0
  155. package/dist/press-kit/articles/reading-time.d.ts +9 -0
  156. package/dist/press-kit/articles/routes.d.ts +52 -0
  157. package/dist/press-kit/articles/server-core.d.ts +461 -0
  158. package/dist/press-kit/articles/server-ui.d.ts +31 -0
  159. package/dist/press-kit/articles/types.d.ts +316 -0
  160. package/dist/press-kit/articles/widget-styles.d.ts +8 -0
  161. package/dist/reputation/index.js +3 -3
  162. package/dist/reputation/server.js +2 -2
  163. package/dist/revalidate/index.js +2 -2
  164. package/dist/runtime/index.js +5 -4
  165. package/dist/seo/client.js +6 -6
  166. package/dist/seo/index.js +7 -7
  167. package/dist/seo/llms.js +8 -8
  168. package/dist/seo/register-sitemap-cli.js +1 -1
  169. package/dist/seo/sitemap.js +6 -6
  170. package/dist/server/index.js +3 -2
  171. package/dist/shared/build-entries.d.ts +2 -1
  172. package/dist/shared/clientApiConfig.d.ts +2 -0
  173. package/dist/shared/import-specifiers.d.ts +1 -1
  174. package/dist/shared/index.d.ts +6 -0
  175. package/dist/shared/index.js +8 -0
  176. package/dist/shared/version.d.ts +1 -1
  177. package/dist/signal/index.js +2 -2
  178. package/dist/sitemap/index.js +6 -6
  179. package/dist/sync/index.js +6 -6
  180. package/dist/website/images.js +4 -4
  181. package/dist/website/index.js +7 -7
  182. package/dist/website/popups.js +6 -6
  183. package/dist/{writeLLMsTxt-OS2WBSLM.js → writeLLMsTxt-VKHCM5IS.js} +5 -5
  184. package/docs/MIGRATING-TO-PRESS-KIT.md +83 -0
  185. package/docs.json +145 -29
  186. package/package.json +15 -5
  187. package/src/articles/README.md +5 -360
  188. package/src/mcp/README.md +16 -0
  189. package/src/og/README.md +1 -1
  190. package/src/runtime/README.md +4 -0
  191. package/dist/SiteChat-6SF7PVUT.js +0 -6
  192. package/dist/SiteDesignReporter-VISQZ5NQ.js +0 -12
  193. package/dist/SitemapSync-VKMVRPZL.js +0 -9
  194. package/dist/article-tables-AXSZOGNW.js +0 -2
@@ -1,21 +1,2 @@
1
- /**
2
- * Scoped CSS for Article and ArticleList default rendering.
3
- *
4
- * Injected via `<style>` in the server component output so consumers
5
- * get a polished article with zero configuration.
6
- *
7
- * All colours use `--sk-*` CSS custom properties with `color-mix()` fallbacks
8
- * that adapt to both light and dark host sites. The host can set:
9
- *
10
- * --sk-primary Brand accent (links, highlights)
11
- * --sk-bg Page background
12
- * --sk-bg-elevated Card / elevated surface background
13
- * --sk-text-primary Main text
14
- * --sk-text-secondary Subdued text
15
- * --sk-text-tertiary Faint text / meta
16
- * --sk-surface-border Subtle border color
17
- *
18
- * If none are set the defaults produce a clean neutral light-mode look.
19
- */
20
- export declare const articleCss: string;
21
- export declare const articleListCss: string;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/article-styles';
@@ -1,12 +1,2 @@
1
- /**
2
- * Server-rendered table scrolling. Keep the author's table markup intact so
3
- * captions, header associations, links and table semantics survive unchanged.
4
- */
5
- /**
6
- * Single source of truth for default article table wrappers. Safe to call twice;
7
- * already wrapped tables and HTML examples are left alone. This is a layout
8
- * transform, not an HTML sanitizer: content still follows the host's trust policy.
9
- */
10
- export declare function wrapArticleTables(html: string): string;
11
- /** Native overflow only when content needs it; small tables retain their layout. */
12
- export declare const articleTableCss: string;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/article-tables';
@@ -1,13 +1,2 @@
1
- import type { CSSProperties } from 'react';
2
- import type { Article } from './types';
3
- export interface ArticleArtwork {
4
- src: string | undefined;
5
- alt: string;
6
- composed: boolean;
7
- }
8
- type ArtworkSource = Pick<Article, 'title' | 'featured_image' | 'featured_image_alt' | 'editorial_image' | 'editorial_image_alt'>;
9
- /** Single source of truth for article artwork versus complete promotional cards. */
10
- export declare function resolveArticleArtwork(post: ArtworkSource, placement?: 'article' | 'card'): ArticleArtwork;
11
- /** Preserve generated text and graphics across every stock card surface. */
12
- export declare function articleArtworkImageStyle(artwork: ArticleArtwork): CSSProperties | undefined;
13
- export {};
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/artwork';
@@ -1,72 +1,2 @@
1
- /**
2
- * @sonordev/site-kit/articles — Author JSON-LD (pure)
3
- *
4
- * Split out of `./server-core` on purpose. Everything here is a pure function:
5
- * it maps an `ArticleAuthor` to schema objects and touches no env, no config,
6
- * and no network. It only ever lived in `server-core` because the other author
7
- * helpers there (`getAuthorBySlug`, `getAuthorPosts`) do fetch.
8
- *
9
- * `AuthorPage` is exported from the client-stamped `@sonordev/site-kit/articles`
10
- * barrel (see `./index.ts`), so importing these from `server-core` dragged that
11
- * whole server module — its `x-api-key` fetches included — into the browser
12
- * bundle. Keeping the pure half here means `AuthorPage` can stay in the barrel
13
- * without pulling a single line of server code with it.
14
- *
15
- * Anything added here must stay pure. If it needs an API key or a fetch, it
16
- * belongs in `./server-core`, not in this file.
17
- *
18
- * Identity model (single source of truth for every author node the kit emits):
19
- * - The author page is a `ProfilePage` whose `mainEntity` is the `Person`
20
- * (Google's profile-page markup for author pages).
21
- * - The `Person` carries one `@id` everywhere it appears (`authorEntityId`):
22
- * the row's `entity_id` when the person has a cross-site identity (e.g.
23
- * https://example.com/#person), else `<author profile URL>#person`.
24
- * - Article bylines (`generateArticleAuthorNode`) reference that same `@id`,
25
- * so an article, its author page and the person's own site describe one
26
- * person, which is what a Knowledge Panel is built from.
27
- */
28
- import type { ArticleAuthor } from './types';
29
- import { type PublicationRoutingOptions } from './routes';
30
- export type AuthorSchemaOptions = PublicationRoutingOptions & {
31
- siteUrl?: string;
32
- siteName?: string;
33
- };
34
- /**
35
- * Single source of truth for an author's Person `@id`.
36
- *
37
- * The row's `entity_id` (one id shared by every site that describes the
38
- * person) wins. Otherwise the Person lives at `<profile URL>#person`. A
39
- * relative profile URL gives no `@id`: an id must be absolute to mean the
40
- * same thing on every page.
41
- */
42
- export declare function authorEntityId(author: Pick<ArticleAuthor, 'entity_id'>, profileUrl?: string): string | undefined;
43
- /**
44
- * The bare `Person` for an author, with no `@context`, for embedding in a
45
- * larger graph (an Organization's `founder`, an `@graph` array). Author pages
46
- * want `generateAuthorSchema`, which wraps this in a `ProfilePage`.
47
- */
48
- export declare function generateAuthorPersonSchema(author: ArticleAuthor, options?: AuthorSchemaOptions): Record<string, unknown>;
49
- /**
50
- * JSON-LD for an author page: a `ProfilePage` whose `mainEntity` is the
51
- * author's `Person`. Render it once per author page (`AuthorPage` does, unless
52
- * its `jsonLd` prop is false).
53
- */
54
- export declare function generateAuthorSchema(author: ArticleAuthor, options?: AuthorSchemaOptions): object;
55
- /**
56
- * The `author` node for article JSON-LD. Single source of truth for bylines:
57
- * generateArticleSchema, generateClusterArticleSchema and stored schema_json
58
- * (via withArticleAuthorIdentity) all route through here.
59
- *
60
- * Links to an author page only when one is known to exist: the row's
61
- * `author_page_url`, or the site declaring `authorPages` in its routing. A
62
- * bare string byline stays a named Person.
63
- */
64
- export declare function generateArticleAuthorNode(author: ArticleAuthor | string | null | undefined, options?: AuthorSchemaOptions): Record<string, unknown> | undefined;
65
- /**
66
- * Attach the author's identity to an article node from stored schema_json
67
- * (built by Signal at publish time, frozen in the row). Adds `@id` and `url`
68
- * from generateArticleAuthorNode when the stored byline is a Person with the
69
- * same name and lacks them; stored values always win and nothing else in the
70
- * node changes. Non-article nodes pass through untouched.
71
- */
72
- export declare function withArticleAuthorIdentity(node: unknown, author: ArticleAuthor | string | null | undefined, options?: AuthorSchemaOptions): unknown;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/author-schema';
@@ -1,14 +1,2 @@
1
- import type { ArticleAuthor } from './types';
2
- export interface AuthorSocialLink {
3
- label: string;
4
- href: string;
5
- }
6
- /**
7
- * Single source of truth for author social display.
8
- *
9
- * The real blog_authors columns are linkedin_url / twitter_url / website_url
10
- * (E-E-A-T fields); `social_links` / `website` are the legacy shape that no
11
- * API response ever carried. Real columns win; legacy handles get their host
12
- * prefixed unless they are already full URLs.
13
- */
14
- export declare function getAuthorSocialLinks(author: Pick<ArticleAuthor, 'linkedin_url' | 'twitter_url' | 'website_url' | 'website' | 'social_links'>): AuthorSocialLink[];
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/author-social';
@@ -1,17 +1,2 @@
1
- /**
2
- * Excerpt sanitizing for article metadata, schema and feeds.
3
- *
4
- * Pure (no `server-only` chain) so it is unit-testable and safe to reuse.
5
- * Source of truth for turning a stored excerpt into display-safe prose.
6
- */
7
- /**
8
- * Turn a stored excerpt into something safe to put in a meta description,
9
- * a schema `description`, or an RSS `<description>`.
10
- *
11
- * The AI article pipeline stores content as JSON sections
12
- * (`{"heading": "## ...", "content": "## ...\n\nIf you're asking **how**..."}`)
13
- * and that value can ship verbatim into <meta name="description">, leaving a
14
- * SERP snippet of raw JSON with markdown asterisks and literal \n. Parse the
15
- * sections out, strip markdown, and cap at a sentence boundary.
16
- */
17
- export declare function sanitizeExcerpt(raw: string | undefined | null, maxLength?: number): string;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/excerpt';
@@ -1,79 +1,2 @@
1
- /**
2
- * @sonordev/site-kit/articles
3
- *
4
- * Complete article integration for Sonor-managed content.
5
- * Create posts in the Sonor dashboard, automatically embedded in your site.
6
- *
7
- * Async server components (PublicationLayout, ArticleList, Article, PublicationSidebar,
8
- * RelatedPosts, the *Page helpers) come from `articles/server-ui`. This entry is
9
- * 'use client'-stamped, so importing them from here hands Next an async
10
- * component across a client boundary and the route 500s in production.
11
- *
12
- * @example
13
- * ```tsx
14
- * // Publication index page — both from server-ui; this barrel is for client components only
15
- * import { ArticleList, PublicationLayout } from '@sonordev/site-kit/articles/server-ui'
16
- *
17
- * export default function PublicationPage() {
18
- * return (
19
- * <PublicationLayout hero={{ title: 'Blog', subtitle: 'Latest articles' }}>
20
- * <ArticleList showCategoryFilter showPagination />
21
- * </PublicationLayout>
22
- * )
23
- * }
24
- * ```
25
- *
26
- * @example
27
- * ```tsx
28
- * // Single post page: UI from server-ui, data/metadata from server
29
- * import { Article } from '@sonordev/site-kit/articles/server-ui'
30
- * import { generateArticleMetadata, generateArticleStaticParams } from '@sonordev/site-kit/articles/server'
31
- *
32
- * export const generateStaticParams = generateArticleStaticParams
33
- * export async function generateMetadata({ params }) {
34
- * return generateArticleMetadata(params.slug, { siteName: 'My Site' })
35
- * }
36
- *
37
- * export default function Post({ params }) {
38
- * return <Article slug={params.slug} showRelated showToc />
39
- * }
40
- * ```
41
- */
42
- export type { ArticleServerProps, ArticleStyles } from './Article';
43
- export type { ArticleListServerProps, ArticleListStyles } from './ArticleList';
44
- export type { PublicationSidebarProps } from './PublicationSidebar';
45
- export { NewsletterWidget } from './NewsletterWidget';
46
- export type { NewsletterWidgetProps } from './NewsletterWidget';
47
- export type { PublicationLayoutProps, PublicationPageProps, ArticlePageProps, CategoryPageProps } from './PublicationLayout';
48
- export { AuthorCard } from './AuthorCard';
49
- export { AuthorPage } from './AuthorPage';
50
- export { TableOfContents } from './TableOfContents';
51
- export { ServiceCallout, ServiceCallouts } from './ServiceCallout';
52
- export type { ServiceCalloutProps } from './ServiceCallout';
53
- export { ArticleFAQ } from './ArticleFAQ';
54
- export type { ArticleEditorialPhoto } from './types';
55
- export type { ArticleFAQProps, FaqItem } from './ArticleFAQ';
56
- export { ClusterNavigation } from './ClusterNavigation';
57
- export type { ClusterNavigationProps } from './ClusterNavigation';
58
- /**
59
- * `ClusterLandingPage` is deliberately NOT re-exported here — import it from
60
- * `@sonordev/site-kit/articles/server-ui`.
61
- *
62
- * This barrel is stamped `'use client'` at build time (it is listed in
63
- * `CLIENT_ENTRIES`, `src/shared/build-entries.ts`), so every module it reaches
64
- * is client code by declaration. `ClusterLandingPage` is an async component that
65
- * awaits `getTopicCluster` from `./server-core`, so exporting it from here put
66
- * that module's `x-api-key` fetch into the browser bundle (confirmed in a real
67
- * site's build, in `.next/static/chunks/`). It also could never have
68
- * worked as a client component: async components are server-only.
69
- *
70
- * The type stays — `export type` is erased at build time and reaches no runtime
71
- * module, so it keeps `import type { ClusterLandingPageProps }` working for
72
- * existing consumers.
73
- */
74
- export type { ClusterLandingPageProps } from './ClusterLandingPage';
75
- export * from './types';
76
- export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolvePublicationUrl } from './routes';
77
- export type { ArticleRoutePost, PublicationRoutingOptions } from './routes';
78
- export { resolveArticleArtwork } from './artwork';
79
- export { addExternalLinkTargets, linkClassificationHost, normalizeSiteHost, resolvePublicationSiteUrl, } from './processArticleHtml';
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/index';
@@ -1,21 +1,26 @@
1
1
  'use client';
2
- import { NewsletterShell } from '../chunk-SC4MZGWZ.js';
3
- export { ArticleFAQ } from '../chunk-GKGSXUVQ.js';
4
- import { getAuthorSocialLinks, readingTimeMinutes } from '../chunk-FV2VD7WM.js';
5
- export { ClusterNavigation, ServiceCallout, ServiceCallouts } from '../chunk-FV2VD7WM.js';
6
- import '../chunk-GYF2ULVO.js';
7
- export { addExternalLinkTargets, linkClassificationHost, normalizeSiteHost, resolvePublicationSiteUrl } from '../chunk-L5UOHS6E.js';
8
- import { generateAuthorSchema, resolveArticleArtwork, articleArtworkImageStyle } from '../chunk-QXMIKDOL.js';
9
- export { resolveArticleArtwork } from '../chunk-QXMIKDOL.js';
10
- import { createPublicationRoutes } from '../chunk-WMVK77ND.js';
11
- export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolvePublicationUrl } from '../chunk-WMVK77ND.js';
2
+ import { NewsletterShell } from '../chunk-LBDWAXAO.js';
3
+ export { ArticleFAQ } from '../chunk-BVB5FBAA.js';
4
+ import { getAuthorSocialLinks, readingTimeMinutes } from '../chunk-BC7JMY4Z.js';
5
+ export { ClusterNavigation, ServiceCallout, ServiceCallouts } from '../chunk-BC7JMY4Z.js';
6
+ import '../chunk-DJAYFHVF.js';
7
+ export { addExternalLinkTargets, linkClassificationHost, normalizeSiteHost, resolvePublicationSiteUrl } from '../chunk-5D7ZISUP.js';
8
+ import { generateAuthorSchema, resolveArticleArtwork, articleArtworkImageStyle } from '../chunk-SNRE3ZVZ.js';
9
+ export { resolveArticleArtwork } from '../chunk-SNRE3ZVZ.js';
10
+ import '../chunk-H72ZFO3F.js';
11
+ import { createPublicationRoutes } from '../chunk-4K735O3J.js';
12
+ export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolvePublicationUrl } from '../chunk-4K735O3J.js';
12
13
  import { safeJsonLd } from '../chunk-4KZ6W3ZH.js';
14
+ import '../chunk-MJP63SSS.js';
13
15
  import '../chunk-YVKRYQRG.js';
16
+ import '../chunk-FESKKJAS.js';
17
+ import '../chunk-A4CC4ZG3.js';
18
+ import '../chunk-W7OPEMGJ.js';
14
19
  import '../chunk-PKBMQBKP.js';
15
20
  import React, { useState, Suspense, useEffect } from 'react';
16
21
  import { jsx, jsxs } from 'react/jsx-runtime';
17
22
 
18
- var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-DTE4KKXV.js'));
23
+ var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-NFNF33V3.js'));
19
24
  function NewsletterWidget({
20
25
  title = "Subscribe to Our Newsletter",
21
26
  description = "Get the latest posts delivered straight to your inbox.",
@@ -1,46 +1,2 @@
1
- /**
2
- * Google News sitemap and feed-size helpers. Pure, environment-free: the
3
- * server helpers in server-core fetch the posts and hand them here, so the XML
4
- * rules can be tested without a network.
5
- *
6
- * News sitemap rules (https://developers.google.com/search/docs/crawling-indexing/sitemaps/news-sitemap):
7
- * only articles published in the last two days, at most 1,000 URLs, each with
8
- * a publication name, language and publication date. Older articles belong in
9
- * the ordinary sitemap, which already lists them.
10
- */
11
- import { type PublicationRoutingOptions, type ArticleRoutePost } from './routes';
12
- /** Google only reads articles from the last two days in a News sitemap. */
13
- export declare const NEWS_SITEMAP_WINDOW_MS: number;
14
- /** Google's cap per News sitemap. */
15
- export declare const NEWS_SITEMAP_MAX_URLS = 1000;
16
- /**
17
- * Items a feed carries by default. Feeds hold each post's full HTML, so a
18
- * 100-post feed ran past half a megabyte, which is where some readers and
19
- * aggregators stop fetching. Readers poll often; 20 recent items is the
20
- * common convention, and older posts stay in the sitemap.
21
- */
22
- export declare const FEED_DEFAULT_ITEMS = 20;
23
- export interface NewsSitemapPost extends ArticleRoutePost {
24
- title: string;
25
- published_at?: string | null;
26
- }
27
- export interface NewsSitemapOptions extends PublicationRoutingOptions {
28
- siteUrl: string;
29
- /** The publication name, exactly as it appears on the articles (e.g. "The Journal by Example Co."). */
30
- publicationName: string;
31
- /** ISO 639 language code. Defaults to "en". */
32
- language?: string;
33
- }
34
- export declare function escapeXml(text: string): string;
35
- /**
36
- * Wrap HTML in CDATA. A literal `]]>` inside the post would close the section
37
- * early and break the whole feed, so it's split across two sections.
38
- */
39
- export declare function cdata(html: string): string;
40
- /** The posts a News sitemap may list: published in the window, newest first. */
41
- export declare function recentNewsPosts<T extends NewsSitemapPost>(posts: T[], now?: Date): T[];
42
- /**
43
- * Build a Google News sitemap. With no post in the window it's a valid, empty
44
- * urlset, which Google accepts; it fills again on the next publish.
45
- */
46
- export declare function buildNewsSitemapXml(posts: NewsSitemapPost[], options: NewsSitemapOptions, now?: Date): string;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/news-sitemap';
@@ -1,34 +1,2 @@
1
- /**
2
- * Post-process Sonor/article HTML for safe, consistent link behavior.
3
- * Server-safe string transforms only (no DOM).
4
- */
5
- /**
6
- * The host `addExternalLinkTargets` compares links against to decide whether a
7
- * link is internal (same tab) or external (`target="_blank"`). Lowercased,
8
- * leading `www.` stripped, so `www.example.com` and `example.com` count as the
9
- * same site; returns '' for anything unparseable.
10
- *
11
- * NOT the multi-site host normalizer. That is `normalizeSiteHost` in
12
- * `sites/normalize`, which keeps `www.` because `www.example.com` and
13
- * `example.com` can be different sub-sites of one Sonor project. This used to
14
- * share that name, so the two were easy to swap by accident.
15
- */
16
- export declare function linkClassificationHost(siteUrl: string): string;
17
- /**
18
- * @deprecated Renamed to {@link linkClassificationHost} (same behavior: strips
19
- * `www.`). It shared a name with the multi-site `normalizeSiteHost` from
20
- * `sites/normalize`, which keeps `www.`. Kept so existing imports from
21
- * `@sonordev/site-kit/articles` still work.
22
- */
23
- export declare const normalizeSiteHost: typeof linkClassificationHost;
24
- /**
25
- * Resolve canonical site URL for link classification.
26
- * Pass `explicit` from props when env vars are not set (e.g. non-Vercel hosts).
27
- */
28
- export declare function resolvePublicationSiteUrl(explicit?: string): string;
29
- /**
30
- * Add `target="_blank"` and `rel="noopener noreferrer"` to external http(s) links.
31
- * Same registrable host (with or without `www`) is treated as internal.
32
- * Skips anchors that already set `target`.
33
- */
34
- export declare function addExternalLinkTargets(html: string, siteUrl: string): string;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/processArticleHtml';
@@ -1,26 +1,2 @@
1
- import type { ArticleCategory, Article } from './types';
2
- export interface ArticleReadConfig {
3
- apiUrl: string;
4
- apiKey: string;
5
- /** Sub-site host override. Omit to resolve from NEXT_PUBLIC_SITE_URL. */
6
- site?: string;
7
- }
8
- /** GET /public/articles/posts/:slug — null when missing or on any failure. */
9
- export declare function fetchArticleBySlug({ apiUrl, apiKey, site }: ArticleReadConfig, slug: string): Promise<Article | null>;
10
- /** GET /public/articles/categories — [] on any failure. */
11
- export declare function fetchArticleCategories({ apiUrl, apiKey, site }: ArticleReadConfig): Promise<ArticleCategory[]>;
12
- /**
13
- * POST /public/articles/related — [] on any failure.
14
- *
15
- * `/public/articles/*`, not `/api/public/articles/*`: public-article.controller is one of
16
- * only two public controllers whose @Controller() omits the `api/` segment.
17
- * The body is snake_case `current_post_id` (the controller looks the post up
18
- * by id — there is no slug path), and `site` rides in the body because this is
19
- * the one article read that isn't a GET.
20
- *
21
- * `revalidate` is optional so <RelatedPosts>, which never set a fetch cache
22
- * lifetime, keeps rendering exactly as it did.
23
- */
24
- export declare function fetchRelatedArticles({ apiUrl, apiKey, site }: ArticleReadConfig, currentPostId: string, limit: number, cache?: {
25
- revalidate?: number;
26
- }): Promise<Article[]>;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/public-reads';
@@ -1,9 +1,2 @@
1
- import type { Article } from './types';
2
- /**
3
- * Single source of truth for reading-time display.
4
- *
5
- * The DB/API column is `reading_time` (blog_posts) — `reading_time_minutes`
6
- * never existed server-side and exists on the type only for callers that
7
- * pre-map their own data. Every "X min read" chip resolves through here.
8
- */
9
- export declare function readingTimeMinutes(post: Pick<Article, 'reading_time' | 'reading_time_minutes'>): number | null;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/reading-time';
@@ -1,52 +1,2 @@
1
- /** Shared, environment-free publication routes for server helpers and article UI. */
2
- export interface ArticleRoutePost {
3
- slug: string;
4
- category?: string | {
5
- slug?: string;
6
- name?: string;
7
- } | null;
8
- canonical_url?: string | null;
9
- }
10
- /**
11
- * Where a publication lives when a site doesn't say. A site whose articles
12
- * already live at another path (/article, /insights, /theforge) passes basePath;
13
- * changing a live URL is an SEO decision, never a default's.
14
- */
15
- export declare const DEFAULT_PUBLICATION_PATH = "/articles";
16
- export interface PublicationRoutingOptions {
17
- /** Publication root, e.g. /theforge or /news. Defaults to DEFAULT_PUBLICATION_PATH (/articles). */
18
- basePath?: string;
19
- /** Use /publication/category/post instead of /publication/post. */
20
- includeCategoryInPath?: boolean;
21
- /** Fallback category for partial cluster records. */
22
- category?: string;
23
- /** A custom local article path. Receives the post's slug and category. */
24
- postPath?: (post: ArticleRoutePost) => string;
25
- /** A custom category destination, for example /theforge?category=guides. */
26
- categoryPath?: (slug: string) => string;
27
- /**
28
- * Whether this site serves author pages. `true` means they live at the
29
- * default `<publication>/author/<slug>`; a function gives a custom path, for
30
- * example ``(slug) => `/author/${slug}` `` when author pages sit at the site
31
- * root. Article JSON-LD links bylines to author pages ONLY when this is set
32
- * (or the author row has `author_page_url`), because most sites have none
33
- * and a byline URL that 404s is worse than no URL.
34
- */
35
- authorPages?: boolean | ((slug: string) => string);
36
- }
37
- export declare function articleCategorySlug(category: ArticleRoutePost['category']): string;
38
- /** Single source of truth for publication paths. Custom routes never change OG artwork. */
39
- export declare function createPublicationRoutes(options?: PublicationRoutingOptions): {
40
- index: string;
41
- post(post: ArticleRoutePost): string;
42
- category(slug: string): string;
43
- cluster: (slug: string) => string;
44
- author: (slug: string) => string;
45
- rss: string;
46
- atom: string;
47
- };
48
- export declare function resolvePublicationUrl(path: string, siteUrl?: string): string;
49
- /** Metadata, feeds, sitemaps and generated schemas agree on a supplied canonical. */
50
- export declare function resolveArticleUrl(post: ArticleRoutePost, options?: PublicationRoutingOptions & {
51
- siteUrl?: string;
52
- }): string;
1
+ /** @deprecated Import from @sonordev/press-kit instead. Compatibility build uses the same canonical source. */
2
+ export * from '../press-kit/articles/routes';