@proveanything/smartlinks 1.13.13 → 1.13.14

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.
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.13.13 | Generated: 2026-05-15T11:06:27.909Z
3
+ Version: 1.13.14 | Generated: 2026-05-15T11:37:00.944Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -5140,7 +5140,9 @@ interface RouteChangeMessage {
5140
5140
  type: 'smartlinks-route-change';
5141
5141
  path: string;
5142
5142
  context: Record<string, string>;
5143
- state: Record<string, string>;
5143
+ state: Record<string, string> & {
5144
+ parentPath?: string;
5145
+ };
5144
5146
  appId?: string;
5145
5147
  }
5146
5148
  ```
@@ -308,6 +308,7 @@ Now that you understand the core concepts, see the implementation guides:
308
308
  - **[containers.md](./containers.md)** — Build full-page embedded experiences
309
309
  - **[mpa.md](./mpa.md)** — Multi-page app architecture (optional)
310
310
  - **[iframe-responder.md](./iframe-responder.md)** — Parent-side iframe integration
311
+ - **[portal-back-button.md](./portal-back-button.md)** — Embedded-app "up" navigation and portal back-button behaviour
311
312
 
312
313
  ---
313
314
 
@@ -316,4 +317,5 @@ Now that you understand the core concepts, see the implementation guides:
316
317
  - [theme.system.md](./theme.system.md) — Theming and CSS variables
317
318
  - [ai.md](./ai.md) — AI assistant integration
318
319
  - [deep-link-discovery.md](./deep-link-discovery.md) — Deep linking patterns
320
+ - [portal-back-button.md](./portal-back-button.md) — Portal shell back-button behavior for hierarchical embeds
319
321
  - [manifests.md](./manifests.md) — App manifest configuration
@@ -141,6 +141,8 @@ const responder = new smartlinks.IframeResponder({
141
141
  });
142
142
  ```
143
143
 
144
+ If your app has hierarchical screens, include `state.parentPath` in each `smartlinks-route-change` message so the portal shell can treat its top back button as "up" navigation instead of exiting the embed. See the [Portal Back Button guide](portal-back-button.md) for the contract and recommended router pattern.
145
+
144
146
  ### Local Development Override
145
147
 
146
148
  ```typescript
@@ -377,7 +379,7 @@ The responder handles these message types from the iframe:
377
379
  type: 'smartlinks-route-change',
378
380
  path: '/products/wine-123',
379
381
  context: { collectionId: 'acme-wines', appId: 'warranty' },
380
- state: { tab: 'details' }
382
+ state: { tab: 'details', parentPath: '/products' }
381
383
  }
382
384
  ```
383
385
 
@@ -439,6 +441,7 @@ import type {
439
441
  5. **Validate tokens** server-side for security
440
442
  6. **Set height dynamically** based on content using `onResize`
441
443
  7. **Sync routes** with parent navigation for better UX
444
+ 8. **Set `parentPath`** for routes that have a meaningful parent screen in the app hierarchy
442
445
 
443
446
  ## Troubleshooting
444
447
 
@@ -461,3 +464,7 @@ import type {
461
464
  - Verify cache storage option is supported (sessionStorage/localStorage)
462
465
  - Check browser storage isn't disabled
463
466
  - Clear cache and retry with `smartlinks.cache.clear()`
467
+
468
+ ### Portal back exits the app too early
469
+ - Set `state.parentPath` on route changes for screens that should navigate "up" inside the app.
470
+ - Make sure the receiving app listens for `smartlinks-navigate` if the SDK version in use does not already handle it.
package/dist/docs/mpa.md CHANGED
@@ -122,6 +122,8 @@ The parent SmartLinks platform embeds apps via iframe:
122
122
 
123
123
  Context parameters (`collectionId`, `appId`, `productId`, `proofId`) are passed as URL query params and read via the iframe responder. See the [iframe Responder guide](iframe-responder.md) for the full context injection API.
124
124
 
125
+ If the embedded app exposes nested screens, document its "up" navigation path with the [Portal Back Button guide](portal-back-button.md) so the shell's back button stays inside the app when appropriate.
126
+
125
127
  ---
126
128
 
127
129
  ## Related Guides
@@ -133,3 +135,4 @@ Context parameters (`collectionId`, `appId`, `productId`, `proofId`) are passed
133
135
  | [Executor Model](executor.md) | Executor bundle: SEO, LLM content, config mutations |
134
136
  | [AI-Native App Manifests](manifests.md) | How manifests wire all bundles together for AI discovery |
135
137
  | [iframe Responder](iframe-responder.md) | Reading context params inside the iframe |
138
+ | [Portal Back Button](portal-back-button.md) | Hierarchy-aware back navigation for embedded apps |
@@ -64,6 +64,7 @@ The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive document
64
64
  | **Mobile Admin Container** | `docs/mobile-admin-container.md` | Building a separate Capacitor-aware mobile admin bundle for field operators |
65
65
  | **Executors** | `docs/executor.md` | Building executor bundles for SEO, LLM content, programmatic config |
66
66
  | **Deep Linking** | `docs/deep-link-discovery.md` | URL state management, navigable states, portal menus, AI nav |
67
+ | **Portal Back Button** | `docs/portal-back-button.md` | Hierarchy-aware "up" navigation inside embedded apps |
67
68
  | **Interactions** | `docs/interactions.md` | Business events, outcomes, voting, competitions, and journey triggers |
68
69
  | **AI-Native Manifests** | `docs/manifests.md` | `app.manifest.json`, `app.admin.json`, `ai-guide.md` structure |
69
70
  | **App Config Files** | `docs/app-manifest.md` | Full field-by-field reference for both JSON config files |
@@ -86,6 +87,7 @@ The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive document
86
87
  - **SmartLinks NPM module** — All data access and platform interaction goes through `@proveanything/smartlinks`
87
88
  - **No standalone auth** — Authentication is handled by the parent SmartLinks platform
88
89
  - **Multi-page build** — Separate bundles for public and admin — see `docs/mpa.md`
90
+ - **Embedded back navigation** — Use `docs/portal-back-button.md` when a sub-app has a real content hierarchy
89
91
 
90
92
  ---
91
93
 
@@ -0,0 +1,95 @@
1
+ # Portal Back Button
2
+
3
+ > **For sub-app authors.** This guide explains how to make the portal's top back button behave like hierarchy-aware "up" navigation inside an embedded app.
4
+
5
+ When a SmartLinks app is embedded inside the portal shell, the shell can render a top-level back button. By default that button exits the app entirely. That is correct for flat screens, but wrong for apps with internal hierarchy such as lists, detail pages, wizards, or nested checkout flows.
6
+
7
+ This document describes the contract for telling the portal where "up" goes from the current screen so the shell can keep the app mounted and route to the correct parent screen instead of leaving the embed.
8
+
9
+ ## Why "up", not browser back
10
+
11
+ Browser back replays history. If a user navigates `list -> item A -> list -> item B`, browser back can yo-yo between detail and list screens in a way that feels wrong for an app chrome back button.
12
+
13
+ "Up" navigates the content hierarchy instead: `item B -> list -> exit app`. It is single-direction and idempotent. Only your app's router knows that hierarchy, so the portal cannot infer it on its own.
14
+
15
+ ## The contract
16
+
17
+ When your app posts `smartlinks-route-change` messages, include a `parentPath` field inside `state` for the current screen:
18
+
19
+ ```ts
20
+ window.parent.postMessage({
21
+ type: 'smartlinks-route-change',
22
+ path: '/items/123',
23
+ context: { collectionId: 'auction-2026', appId: 'auction' },
24
+ state: {
25
+ parentPath: '/items',
26
+ },
27
+ appId: 'auction',
28
+ }, '*');
29
+ ```
30
+
31
+ | `state.parentPath` value | Portal back-button behaviour |
32
+ | --- | --- |
33
+ | `'/items'` (or any string) | The portal posts `smartlinks-navigate` to the iframe with that path and keeps the app mounted. |
34
+ | `''`, missing, or omitted | The portal falls back to the default behaviour and exits the app. |
35
+
36
+ The portal only uses `parentPath` when it is present on the current route. Query-string changes, tab switches, and modal state should keep the same parent path.
37
+
38
+ ## Recommended pattern
39
+
40
+ Keep the hierarchy mapping close to your route definitions:
41
+
42
+ ```ts
43
+ const PARENTS: Record<string, (params: any) => string | null> = {
44
+ '/': () => null,
45
+ '/items': () => null,
46
+ '/items/:id': () => '/items',
47
+ '/items/:id/bid': ({ id }) => `/items/${id}`,
48
+ '/checkout': () => '/items',
49
+ };
50
+
51
+ export function getParentPath(pathname: string): string | null {
52
+ // Use your router's path matching here and return the parent route.
53
+ return null;
54
+ }
55
+ ```
56
+
57
+ Then emit `parentPath` whenever the route changes:
58
+
59
+ ```ts
60
+ useDeepLinkSync({
61
+ getParentPath: ({ pathname }) => getParentPath(pathname),
62
+ });
63
+ ```
64
+
65
+ If you do not use `useDeepLinkSync`, post the message yourself and include `parentPath` in `state`.
66
+
67
+ ## Receiving the up-message
68
+
69
+ When the portal consumes `parentPath`, it posts `smartlinks-navigate` back to the iframe:
70
+
71
+ ```ts
72
+ {
73
+ type: 'smartlinks-navigate',
74
+ appId: 'auction',
75
+ path: '/items',
76
+ params: {},
77
+ target: '_self',
78
+ }
79
+ ```
80
+
81
+ Your app should listen for that message and route accordingly. If your SDK release already includes the inbound `smartlinks-navigate` listener, this can be automatic; otherwise add a small `message` listener and call your router manually.
82
+
83
+ ## Reference
84
+
85
+ `state` remains a general `Record<string, string>`. `parentPath` is a recognised optional convention, not a breaking protocol change.
86
+
87
+ ## FAQ
88
+
89
+ **Do I need to push every query-param change as a navigation step?** No. `parentPath` is hierarchy, not history.
90
+
91
+ **What if my up target leaves the app?** Set `parentPath` to `''` or omit it.
92
+
93
+ **Can I disable the portal back button on certain screens?** Not via this protocol. Use the existing `homeScope: 'entry'` portal behaviour if you need the shell back button suppressed.
94
+
95
+ **What about an in-app back button?** Keep it if you want. The portal back is shell chrome; an in-content back is part of the app UI.
package/dist/openapi.yaml CHANGED
@@ -20564,8 +20564,9 @@ components:
20564
20564
  type: string
20565
20565
  state:
20566
20566
  type: object
20567
- additionalProperties:
20568
- type: string
20567
+ additionalProperties: true
20568
+ parentPath:
20569
+ type: string
20569
20570
  appId:
20570
20571
  type: string
20571
20572
  required:
@@ -38,7 +38,9 @@ export interface RouteChangeMessage {
38
38
  type: 'smartlinks-route-change';
39
39
  path: string;
40
40
  context: Record<string, string>;
41
- state: Record<string, string>;
41
+ state: Record<string, string> & {
42
+ parentPath?: string;
43
+ };
42
44
  appId?: string;
43
45
  }
44
46
  export interface SmartlinksIframeMessage {
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.13.13 | Generated: 2026-05-15T11:06:27.909Z
3
+ Version: 1.13.14 | Generated: 2026-05-15T11:37:00.944Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -5140,7 +5140,9 @@ interface RouteChangeMessage {
5140
5140
  type: 'smartlinks-route-change';
5141
5141
  path: string;
5142
5142
  context: Record<string, string>;
5143
- state: Record<string, string>;
5143
+ state: Record<string, string> & {
5144
+ parentPath?: string;
5145
+ };
5144
5146
  appId?: string;
5145
5147
  }
5146
5148
  ```
@@ -308,6 +308,7 @@ Now that you understand the core concepts, see the implementation guides:
308
308
  - **[containers.md](./containers.md)** — Build full-page embedded experiences
309
309
  - **[mpa.md](./mpa.md)** — Multi-page app architecture (optional)
310
310
  - **[iframe-responder.md](./iframe-responder.md)** — Parent-side iframe integration
311
+ - **[portal-back-button.md](./portal-back-button.md)** — Embedded-app "up" navigation and portal back-button behaviour
311
312
 
312
313
  ---
313
314
 
@@ -316,4 +317,5 @@ Now that you understand the core concepts, see the implementation guides:
316
317
  - [theme.system.md](./theme.system.md) — Theming and CSS variables
317
318
  - [ai.md](./ai.md) — AI assistant integration
318
319
  - [deep-link-discovery.md](./deep-link-discovery.md) — Deep linking patterns
320
+ - [portal-back-button.md](./portal-back-button.md) — Portal shell back-button behavior for hierarchical embeds
319
321
  - [manifests.md](./manifests.md) — App manifest configuration
@@ -141,6 +141,8 @@ const responder = new smartlinks.IframeResponder({
141
141
  });
142
142
  ```
143
143
 
144
+ If your app has hierarchical screens, include `state.parentPath` in each `smartlinks-route-change` message so the portal shell can treat its top back button as "up" navigation instead of exiting the embed. See the [Portal Back Button guide](portal-back-button.md) for the contract and recommended router pattern.
145
+
144
146
  ### Local Development Override
145
147
 
146
148
  ```typescript
@@ -377,7 +379,7 @@ The responder handles these message types from the iframe:
377
379
  type: 'smartlinks-route-change',
378
380
  path: '/products/wine-123',
379
381
  context: { collectionId: 'acme-wines', appId: 'warranty' },
380
- state: { tab: 'details' }
382
+ state: { tab: 'details', parentPath: '/products' }
381
383
  }
382
384
  ```
383
385
 
@@ -439,6 +441,7 @@ import type {
439
441
  5. **Validate tokens** server-side for security
440
442
  6. **Set height dynamically** based on content using `onResize`
441
443
  7. **Sync routes** with parent navigation for better UX
444
+ 8. **Set `parentPath`** for routes that have a meaningful parent screen in the app hierarchy
442
445
 
443
446
  ## Troubleshooting
444
447
 
@@ -461,3 +464,7 @@ import type {
461
464
  - Verify cache storage option is supported (sessionStorage/localStorage)
462
465
  - Check browser storage isn't disabled
463
466
  - Clear cache and retry with `smartlinks.cache.clear()`
467
+
468
+ ### Portal back exits the app too early
469
+ - Set `state.parentPath` on route changes for screens that should navigate "up" inside the app.
470
+ - Make sure the receiving app listens for `smartlinks-navigate` if the SDK version in use does not already handle it.
package/docs/mpa.md CHANGED
@@ -122,6 +122,8 @@ The parent SmartLinks platform embeds apps via iframe:
122
122
 
123
123
  Context parameters (`collectionId`, `appId`, `productId`, `proofId`) are passed as URL query params and read via the iframe responder. See the [iframe Responder guide](iframe-responder.md) for the full context injection API.
124
124
 
125
+ If the embedded app exposes nested screens, document its "up" navigation path with the [Portal Back Button guide](portal-back-button.md) so the shell's back button stays inside the app when appropriate.
126
+
125
127
  ---
126
128
 
127
129
  ## Related Guides
@@ -133,3 +135,4 @@ Context parameters (`collectionId`, `appId`, `productId`, `proofId`) are passed
133
135
  | [Executor Model](executor.md) | Executor bundle: SEO, LLM content, config mutations |
134
136
  | [AI-Native App Manifests](manifests.md) | How manifests wire all bundles together for AI discovery |
135
137
  | [iframe Responder](iframe-responder.md) | Reading context params inside the iframe |
138
+ | [Portal Back Button](portal-back-button.md) | Hierarchy-aware back navigation for embedded apps |
package/docs/overview.md CHANGED
@@ -64,6 +64,7 @@ The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive document
64
64
  | **Mobile Admin Container** | `docs/mobile-admin-container.md` | Building a separate Capacitor-aware mobile admin bundle for field operators |
65
65
  | **Executors** | `docs/executor.md` | Building executor bundles for SEO, LLM content, programmatic config |
66
66
  | **Deep Linking** | `docs/deep-link-discovery.md` | URL state management, navigable states, portal menus, AI nav |
67
+ | **Portal Back Button** | `docs/portal-back-button.md` | Hierarchy-aware "up" navigation inside embedded apps |
67
68
  | **Interactions** | `docs/interactions.md` | Business events, outcomes, voting, competitions, and journey triggers |
68
69
  | **AI-Native Manifests** | `docs/manifests.md` | `app.manifest.json`, `app.admin.json`, `ai-guide.md` structure |
69
70
  | **App Config Files** | `docs/app-manifest.md` | Full field-by-field reference for both JSON config files |
@@ -86,6 +87,7 @@ The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive document
86
87
  - **SmartLinks NPM module** — All data access and platform interaction goes through `@proveanything/smartlinks`
87
88
  - **No standalone auth** — Authentication is handled by the parent SmartLinks platform
88
89
  - **Multi-page build** — Separate bundles for public and admin — see `docs/mpa.md`
90
+ - **Embedded back navigation** — Use `docs/portal-back-button.md` when a sub-app has a real content hierarchy
89
91
 
90
92
  ---
91
93
 
@@ -0,0 +1,95 @@
1
+ # Portal Back Button
2
+
3
+ > **For sub-app authors.** This guide explains how to make the portal's top back button behave like hierarchy-aware "up" navigation inside an embedded app.
4
+
5
+ When a SmartLinks app is embedded inside the portal shell, the shell can render a top-level back button. By default that button exits the app entirely. That is correct for flat screens, but wrong for apps with internal hierarchy such as lists, detail pages, wizards, or nested checkout flows.
6
+
7
+ This document describes the contract for telling the portal where "up" goes from the current screen so the shell can keep the app mounted and route to the correct parent screen instead of leaving the embed.
8
+
9
+ ## Why "up", not browser back
10
+
11
+ Browser back replays history. If a user navigates `list -> item A -> list -> item B`, browser back can yo-yo between detail and list screens in a way that feels wrong for an app chrome back button.
12
+
13
+ "Up" navigates the content hierarchy instead: `item B -> list -> exit app`. It is single-direction and idempotent. Only your app's router knows that hierarchy, so the portal cannot infer it on its own.
14
+
15
+ ## The contract
16
+
17
+ When your app posts `smartlinks-route-change` messages, include a `parentPath` field inside `state` for the current screen:
18
+
19
+ ```ts
20
+ window.parent.postMessage({
21
+ type: 'smartlinks-route-change',
22
+ path: '/items/123',
23
+ context: { collectionId: 'auction-2026', appId: 'auction' },
24
+ state: {
25
+ parentPath: '/items',
26
+ },
27
+ appId: 'auction',
28
+ }, '*');
29
+ ```
30
+
31
+ | `state.parentPath` value | Portal back-button behaviour |
32
+ | --- | --- |
33
+ | `'/items'` (or any string) | The portal posts `smartlinks-navigate` to the iframe with that path and keeps the app mounted. |
34
+ | `''`, missing, or omitted | The portal falls back to the default behaviour and exits the app. |
35
+
36
+ The portal only uses `parentPath` when it is present on the current route. Query-string changes, tab switches, and modal state should keep the same parent path.
37
+
38
+ ## Recommended pattern
39
+
40
+ Keep the hierarchy mapping close to your route definitions:
41
+
42
+ ```ts
43
+ const PARENTS: Record<string, (params: any) => string | null> = {
44
+ '/': () => null,
45
+ '/items': () => null,
46
+ '/items/:id': () => '/items',
47
+ '/items/:id/bid': ({ id }) => `/items/${id}`,
48
+ '/checkout': () => '/items',
49
+ };
50
+
51
+ export function getParentPath(pathname: string): string | null {
52
+ // Use your router's path matching here and return the parent route.
53
+ return null;
54
+ }
55
+ ```
56
+
57
+ Then emit `parentPath` whenever the route changes:
58
+
59
+ ```ts
60
+ useDeepLinkSync({
61
+ getParentPath: ({ pathname }) => getParentPath(pathname),
62
+ });
63
+ ```
64
+
65
+ If you do not use `useDeepLinkSync`, post the message yourself and include `parentPath` in `state`.
66
+
67
+ ## Receiving the up-message
68
+
69
+ When the portal consumes `parentPath`, it posts `smartlinks-navigate` back to the iframe:
70
+
71
+ ```ts
72
+ {
73
+ type: 'smartlinks-navigate',
74
+ appId: 'auction',
75
+ path: '/items',
76
+ params: {},
77
+ target: '_self',
78
+ }
79
+ ```
80
+
81
+ Your app should listen for that message and route accordingly. If your SDK release already includes the inbound `smartlinks-navigate` listener, this can be automatic; otherwise add a small `message` listener and call your router manually.
82
+
83
+ ## Reference
84
+
85
+ `state` remains a general `Record<string, string>`. `parentPath` is a recognised optional convention, not a breaking protocol change.
86
+
87
+ ## FAQ
88
+
89
+ **Do I need to push every query-param change as a navigation step?** No. `parentPath` is hierarchy, not history.
90
+
91
+ **What if my up target leaves the app?** Set `parentPath` to `''` or omit it.
92
+
93
+ **Can I disable the portal back button on certain screens?** Not via this protocol. Use the existing `homeScope: 'entry'` portal behaviour if you need the shell back button suppressed.
94
+
95
+ **What about an in-app back button?** Keep it if you want. The portal back is shell chrome; an in-content back is part of the app UI.
package/openapi.yaml CHANGED
@@ -20564,8 +20564,9 @@ components:
20564
20564
  type: string
20565
20565
  state:
20566
20566
  type: object
20567
- additionalProperties:
20568
- type: string
20567
+ additionalProperties: true
20568
+ parentPath:
20569
+ type: string
20569
20570
  appId:
20570
20571
  type: string
20571
20572
  required:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "1.13.13",
3
+ "version": "1.13.14",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",