@soloworks/smking-next 0.21.2 → 0.21.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @soloworks/smking-next
2
2
 
3
+ ## 0.21.3 — 2026-07-03
4
+
5
+ **AEO original-vs-enhanced audits can now fetch the true host HTML.**
6
+
7
+ `<SmkingAEO>` now honors `x-smking-origin-mode: raw` by returning `null`
8
+ before calling the SaaS. This lets Page Zero fetch a customer page's real
9
+ pre-injection HTML for source-change detection, then compare it against the
10
+ served enhanced version. No customer code change; customers already on `^0.21`
11
+ receive it on the next install/update.
12
+
3
13
  ## 0.21.2 — 2026-07-02
4
14
 
5
15
  **CMS taxonomy page types caught up with the SaaS catalog (types only — no runtime change).**
package/bin/install.mjs CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soloworks/smking-next",
3
- "version": "0.21.2",
3
+ "version": "0.21.3",
4
4
  "description": "AI-native SEO (AEO) for Next.js — auto-inject JSON-LD, FAQ, AI summary, and SEO metadata so AI crawlers (ChatGPT, Perplexity, Google AI) can cite your pages.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/sillyleo/smking/tree/main/packages/smking-next",
@@ -65,6 +65,11 @@
65
65
  "perplexity",
66
66
  "smking"
67
67
  ],
68
+ "scripts": {
69
+ "typecheck": "tsc --noEmit",
70
+ "test": "vitest run",
71
+ "test:watch": "vitest"
72
+ },
68
73
  "peerDependencies": {
69
74
  "next": "^15.0.0 || ^16.0.0",
70
75
  "react": "^18.0.0 || ^19.0.0"
@@ -86,10 +91,5 @@
86
91
  "react-dom": "19.2.4",
87
92
  "typescript": "^5",
88
93
  "vitest": "^4.1.5"
89
- },
90
- "scripts": {
91
- "typecheck": "tsc --noEmit",
92
- "test": "vitest run",
93
- "test:watch": "vitest"
94
94
  }
95
- }
95
+ }
package/src/cms-blocks.ts CHANGED
@@ -27,6 +27,35 @@
27
27
  * slug-prefix derived, tag mode targets `taxonomies.slug`.
28
28
  */
29
29
 
30
+ export interface YouTubeEmbedOptions {
31
+ autoplay?: boolean;
32
+ ccLangPref?: string;
33
+ ccLoadPolicy?: boolean;
34
+ color?: "red" | "white";
35
+ controls?: boolean;
36
+ disablekb?: boolean;
37
+ enablejsapi?: boolean;
38
+ end?: number;
39
+ fs?: boolean;
40
+ hl?: string;
41
+ ivLoadPolicy?: "show" | "hide";
42
+ list?: string;
43
+ listType?: "playlist" | "user_uploads";
44
+ loop?: boolean;
45
+ origin?: string;
46
+ playlist?: string;
47
+ playsinline?: boolean;
48
+ relatedMode?: "all" | "same-channel";
49
+ start?: number;
50
+ widgetReferrer?: string;
51
+ }
52
+
53
+ export interface HeroYouTubeProps extends YouTubeEmbedOptions {
54
+ url: string;
55
+ videoId: string;
56
+ thumbnailUrl: string;
57
+ }
58
+
30
59
  export interface HeroProps {
31
60
  title: string;
32
61
  /** Generic visible meta lines. Legacy drafts may still also carry subtitle. */
@@ -39,6 +68,9 @@ export interface HeroProps {
39
68
  /** Legacy single-line fallback for SDK Mode B consumers. */
40
69
  subtitle?: string;
41
70
  image?: { url: string; alt: string };
71
+ /** YouTube hero media. Article body renders the embed; cards / metadata use
72
+ * the thumbnail so list-like pages never mount a player. */
73
+ youtube?: HeroYouTubeProps;
42
74
  cta?: { label: string; href: string };
43
75
  /** Header layout — omitted = the original centred hero; "start" = the
44
76
  * Apple-newsroom-style left-aligned header; "cover" = title-only banner over
@@ -122,22 +154,16 @@ export interface SearchProps {
122
154
  /** Content column vs wide breakout (default wide). Mirrors the media
123
155
  * blocks (image/embed). */
124
156
  widthMode?: "content" | "wide";
157
+ /** Quick-link cluster alignment beside the search trigger. Defaults left. */
158
+ linkAlign?: "left" | "right";
159
+ /** Quick-link visual treatment. Defaults badge. */
160
+ linkStyle?: "badge" | "plain";
125
161
  /** Optional quick links adjacent to search. */
126
162
  links?: SearchQuickLink[];
127
163
  /** Publish-time materialized snapshot — every published page on the site. */
128
164
  snapshot?: NavSnapshotEntry[];
129
165
  }
130
166
 
131
- export interface RecentPostsProps extends ModuleHeader {
132
- /** Author-set number of latest posts to show (1..50). */
133
- limit: number;
134
- /** Content column vs wide breakout (default content). Mirrors the media
135
- * blocks. */
136
- widthMode?: "content" | "wide";
137
- /** Publish-time materialized snapshot — whole-site newest-first. */
138
- snapshot?: NavSnapshotEntry[];
139
- }
140
-
141
167
  /** One author-picked source for nav-related-posts. Same shape as
142
168
  * `CategoryIndexItem` (a category path OR a tag), reused so the source picker
143
169
  * UI stays identical across blocks. */
@@ -369,7 +395,7 @@ export interface ButtonGroupProps {
369
395
  * url = renders nothing on the customer side. `widthMode` matches the other
370
396
  * media blocks (content column vs wide breakout).
371
397
  */
372
- export interface EmbedProps {
398
+ export interface EmbedProps extends YouTubeEmbedOptions {
373
399
  url?: string;
374
400
  caption?: string;
375
401
  widthMode?: "content" | "wide";
@@ -416,6 +442,15 @@ export type LatestNewsSlot =
416
442
  source?: "category-by-path" | "tag";
417
443
  };
418
444
 
445
+ /** Whole-block source mode for `latest-news`. Omitted = `manual` so old
446
+ * blocks keep their curated slots exactly. */
447
+ export type LatestNewsMode =
448
+ | "manual"
449
+ | "latest"
450
+ | "auto-category"
451
+ | "category"
452
+ | "tag";
453
+
419
454
  /**
420
455
  * One materialized `latest-news` card: the resolved article entry (the
421
456
  * article itself for an `article` slot, or the category's latest post for a
@@ -436,8 +471,18 @@ export interface LatestNewsCardSnapshot {
436
471
  * feeds; reuses `NavSnapshotEntry` for each resolved card.
437
472
  */
438
473
  export interface LatestNewsProps extends ModuleHeader {
474
+ /** Whole-block source mode. Omitted/manual uses `slots`; other modes resolve
475
+ * cards dynamically at publish time. */
476
+ mode?: LatestNewsMode;
439
477
  /** Author-curated slots, 3–6, in display order (first = feature card). */
440
478
  slots: LatestNewsSlot[];
479
+ /** Card count for automatic modes. The magazine grid supports 3–6 cards. */
480
+ limit?: number;
481
+ /** Selected category/tag path for `category` / `tag` modes. */
482
+ sourcePath?: string;
483
+ /** Editor-facing label for the selected category/tag; used as the card
484
+ * eyebrow in automatic source modes. */
485
+ sourceLabel?: string;
441
486
  /** Content column vs wide breakout (default wide). Mirrors the media
442
487
  * blocks. */
443
488
  widthMode?: "content" | "wide";
@@ -454,7 +499,6 @@ export type Block =
454
499
  props: NavTaxonomyListProps;
455
500
  }
456
501
  | { component: "search"; id: string; props: SearchProps }
457
- | { component: "nav-recent-posts"; id: string; props: RecentPostsProps }
458
502
  | { component: "nav-related-posts"; id: string; props: RelatedPostsProps }
459
503
  | { component: "article-tags"; id: string; props: ArticleTagsProps }
460
504
  | { component: "nav-category-index"; id: string; props: CategoryIndexProps }
@@ -1,3 +1,5 @@
1
+ import { headers } from "next/headers";
2
+
1
3
  import type { DiscoverParams } from "../types";
2
4
  import { getAeoContent } from "../lib/client";
3
5
  import { safeJson } from "../lib/safe-json";
@@ -16,6 +18,18 @@ const SR_ONLY_STYLE: React.CSSProperties = {
16
18
 
17
19
  export interface SmkingAEOProps extends DiscoverParams {}
18
20
 
21
+ async function wantsOriginBypass(): Promise<boolean> {
22
+ try {
23
+ const requestHeaders = await headers();
24
+ return (
25
+ requestHeaders.get("x-smking-origin-mode")?.trim().toLowerCase() ===
26
+ "raw"
27
+ );
28
+ } catch {
29
+ return false;
30
+ }
31
+ }
32
+
19
33
  /**
20
34
  * Server Component that injects AEO + SEO content for the current
21
35
  * request. Place once in the root layout, inside `<body>`:
@@ -57,6 +71,8 @@ export interface SmkingAEOProps extends DiscoverParams {}
57
71
  * arbitrary content fetched anywhere.
58
72
  */
59
73
  export async function SmkingAEO(props: SmkingAEOProps) {
74
+ if (await wantsOriginBypass()) return null;
75
+
60
76
  const aeo = await getAeoContent(props);
61
77
  if (!aeo || aeo.status !== "ready") return null;
62
78
 
package/src/index.ts CHANGED
@@ -25,7 +25,6 @@ export type {
25
25
  NavLayout,
26
26
  NavSnapshotEntry,
27
27
  NavTaxonomyListProps,
28
- RecentPostsProps,
29
28
  RelatedPostsProps,
30
29
  SearchQuickLink,
31
30
  SearchQuickLinkSource,
@@ -1 +1 @@
1
- export const SDK_VERSION = "0.18.0";
1
+ export const SDK_VERSION = "0.21.3";
package/src/types.ts CHANGED
@@ -85,7 +85,6 @@ export type {
85
85
  NavLayout,
86
86
  NavSnapshotEntry,
87
87
  NavTaxonomyListProps,
88
- RecentPostsProps,
89
88
  RelatedPostsProps,
90
89
  SearchQuickLink,
91
90
  SearchQuickLinkSource,