@proveanything/smartlinks 2.1.2 → 2.1.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.
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.1.2 | Generated: 2026-10-26T14:58:53.408Z
3
+ Version: 2.1.3 | Generated: 2026-10-26T21:00:54.277Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -2585,9 +2585,11 @@ interface AppContainerComponent {
2585
2585
  **DeepLinkEntry** (interface)
2586
2586
  ```typescript
2587
2587
  interface DeepLinkEntry {
2588
+ id?: string;
2588
2589
  title: string;
2589
2590
  path?: string;
2590
2591
  params?: Record<string, string>;
2592
+ accepts?: PublicViewParams;
2591
2593
  widget?: true;
2592
2594
  }
2593
2595
  ```
@@ -7479,6 +7481,7 @@ interface IframeResponderOptions {
7479
7481
  version?: string;
7480
7482
  appUrl?: string;
7481
7483
  initialPath?: string;
7484
+ params?: Record<string, string>;
7482
7485
  isAdmin?: boolean;
7483
7486
  cache?: CachedData;
7484
7487
  onAuthLogin?: (
@@ -326,11 +326,28 @@ Static deep-linkable states built into the app — fixed routes that exist regar
326
326
 
327
327
  See the [Deep Link Discovery guide](deep-link-discovery.md) for the full dual-source pattern (static manifest routes + dynamic `appConfig.linkable`).
328
328
 
329
+ These are the app's **pages that a host opens**: portal menus and tabs, and websites that embed the app
330
+ (websites.md → "Using another app's pages"). A host opens them with its own signed-in session, so one
331
+ app can offer several pages that each know the visitor: book, upcoming bookings, past bookings, change a
332
+ booking.
333
+
334
+ ```json
335
+ "linkable": [
336
+ { "id": "book", "title": "Book an appointment", "path": "/",
337
+ "accepts": { "optional": ["service", "staff", "date"] } },
338
+ { "id": "upcoming", "title": "Your upcoming bookings", "path": "/my-bookings" },
339
+ { "id": "change", "title": "Change a booking", "path": "/booking",
340
+ "accepts": { "required": ["id"] } }
341
+ ]
342
+ ```
343
+
329
344
  | Field | Type | Required | Description |
330
345
  |-------|------|----------|-------------|
346
+ | `id` | string | ❌ | Stable id, unique within the app: hosts and sites refer to the page by it |
331
347
  | `title` | string | ✅ | Human-readable label shown in menus and offered to AI agents |
332
348
  | `path` | string | ❌ | Hash route within the app (defaults to `"/"` if omitted) |
333
- | `params` | object | ❌ | App-specific query params appended to the URL — do **not** include platform params (`collectionId`, `productId`, etc.) |
349
+ | `params` | object | ❌ | Params this entry PINS, appended to the URL — do **not** include platform params (`collectionId`, `productId`, etc.) |
350
+ | `accepts` | `{ required?: string[]; optional?: string[] }` | ❌ | The params a host may supply when it opens the page (e.g. which service to start on) |
334
351
 
335
352
  #### `publicViews`
336
353
 
@@ -371,7 +388,7 @@ An app can have any combination of three setup styles. Only public views are ext
371
388
  | Style | Declared by | Lives | Context |
372
389
  |-------|-------------|-------|---------|
373
390
  | **Portal components** — where the app renders inside portal (collection / product / batch / variant / proof) | module registry `components.*` (set at publish) | Inside portal | Physical twin (QR/NFC scan) |
374
- | **Portal deep links** — the entry points portal menus/tabs/side-menus link to (e.g. list view vs calendar view) | `linkable` / `DeepLinkEntry` | Inside portal | Portal (menu picks the entry) |
391
+ | **App pages** — the entry points portal menus/tabs link to and websites embed (e.g. list vs calendar; book vs my bookings) | `linkable` / `DeepLinkEntry` | Inside a host: portal or a website | The host: its signed-in session, plus the page's `accepts` params |
375
392
  | **Public views** — standalone external screens | `publicViews` (this block) | Outside portal | URL params only |
376
393
 
377
394
  #### `records`
@@ -172,6 +172,9 @@ Both sources use the same entry shape:
172
172
 
173
173
  ```typescript
174
174
  interface DeepLinkEntry {
175
+ /** Stable id, unique within the app (optional): hosts and websites refer to the page by it */
176
+ id?: string;
177
+
175
178
  /** Human-readable label for this state (required) */
176
179
  title: string;
177
180
 
@@ -193,6 +196,13 @@ interface DeepLinkEntry {
193
196
  */
194
197
  params?: Record<string, string>;
195
198
 
199
+ /**
200
+ * The params a host may supply when it opens this page (optional), e.g. a booking page that can
201
+ * start on one service: `{ optional: ['service', 'staff', 'date'] }`. `params` are pinned by the
202
+ * entry; `accepts` are filled in by whoever opens it.
203
+ */
204
+ accepts?: { required?: string[]; optional?: string[] };
205
+
196
206
  /**
197
207
  * When `true`, this entry is also available as a dynamic data context for widgets.
198
208
  *
@@ -211,7 +221,9 @@ interface DeepLinkEntry {
211
221
  |-------|----------|-------|
212
222
  | `title` | ✅ | Displayed in menus and offered to AI agents. Should be concise and human-readable. |
213
223
  | `path` | ❌ | Hash route within the app. Defaults to `/` if omitted. |
224
+ | `id` | ❌ | Stable id for hosts and websites to refer to the page by. |
214
225
  | `params` | ❌ | App-specific query params only. Platform params are injected automatically. |
226
+ | `accepts` | ❌ | The params whoever opens the page may supply (`required` / `optional`). |
215
227
  | `widget` | ❌ | Set to `true` to make this entry selectable in the widget config picker as a dynamic data context. |
216
228
 
217
229
  > **Tip:** Different entries can share the same `path` if they differ by `params` — for example, two entries pointing at `/settings` with different `tab` params.
@@ -103,6 +103,7 @@ interface IframeResponderOptions {
103
103
  version?: 'stable' | 'development'; // App version (default: 'stable')
104
104
  appUrl?: string; // Override URL (for local dev)
105
105
  initialPath?: string; // Initial hash path (e.g., '/settings')
106
+ params?: Record<string, string>; // The page's own params (e.g. { service: 'svc_123' }); context params win
106
107
 
107
108
  // Data
108
109
  cache?: CachedData; // Pre-cached data
@@ -66,6 +66,32 @@ bytes. `_server/` is never served to visitors.
66
66
  doing work that belongs in a server function or a scheduled job.
67
67
  - **No secrets** in the server bundle and no Node built-ins beyond `nodejs_compat`.
68
68
 
69
+ ## Using another app's pages
70
+
71
+ Some apps do a job a site shouldn't rebuild: a booking journey holds the time rules, the clash
72
+ handling and the confirmation; "my bookings" holds who may change what. Those apps declare their pages
73
+ in `linkable` (app-manifest.md), each with a stable `id`, a `path` and the params it `accepts`. A site
74
+ embeds one with **`IframeResponder`** (iframe-responder.md), from the browser:
75
+
76
+ ```typescript
77
+ const site = SL.site.current()
78
+ const responder = new SL.IframeResponder({
79
+ collectionId: site.collectionId,
80
+ appId: 'appointments', // the app's id on this collection
81
+ initialPath: '/my-bookings', // the page's `path`
82
+ params: { service: 'svc_123' }, // what the page `accepts`
83
+ onResize: (h) => { iframe.style.height = `${h}px` },
84
+ })
85
+ iframe.src = await responder.attach(iframe)
86
+ ```
87
+
88
+ - **The visitor's session goes with it.** The page's API calls are proxied through the site, so it
89
+ acts as whoever is signed in to the site (or as a guest). Never pass a token in the URL.
90
+ - **The app must be installed** on the site's collection; its address comes from there.
91
+ - **Show the app's content natively where you can** (its `headless` data: services, staff, events)
92
+ for your own design and SEO, and embed the page only for the part that does the work.
93
+ - Pages render on the client, after load: they aren't part of the server-rendered HTML.
94
+
69
95
  ## Caching
70
96
 
71
97
  The router keeps a rendered page at the edge when your response says it may:
@@ -100,4 +100,6 @@ export declare function buildIframeSrc(options: {
100
100
  secondary?: string;
101
101
  };
102
102
  initialPath?: string;
103
+ /** The page's own params; the context params above always win. */
104
+ params?: Record<string, string>;
103
105
  }): string;
@@ -155,11 +155,16 @@ export class IframeResponder {
155
155
  // URL Building
156
156
  // ===========================================================================
157
157
  buildIframeSrc() {
158
- var _a, _b;
158
+ var _a, _b, _c;
159
159
  if (!this.appUrl) {
160
160
  throw new Error('App URL not resolved');
161
161
  }
162
162
  const params = new URLSearchParams();
163
+ // The page's own params first: the platform's context below always wins.
164
+ for (const [key, value] of Object.entries((_a = this.options.params) !== null && _a !== void 0 ? _a : {})) {
165
+ if (value != null && value !== '')
166
+ params.set(key, String(value));
167
+ }
163
168
  // Required context
164
169
  params.set('collectionId', this.options.collectionId);
165
170
  params.set('appId', this.options.appId);
@@ -171,13 +176,13 @@ export class IframeResponder {
171
176
  if (this.options.isAdmin)
172
177
  params.set('isAdmin', 'true');
173
178
  // Dark mode from collection
174
- const isDark = (_b = (_a = this.cache.collection) === null || _a === void 0 ? void 0 : _a.dark) !== null && _b !== void 0 ? _b : false;
179
+ const isDark = (_c = (_b = this.cache.collection) === null || _b === void 0 ? void 0 : _b.dark) !== null && _c !== void 0 ? _c : false;
175
180
  params.set('dark', isDark ? '1' : '0');
176
181
  // Parent URL for redirects
177
182
  try {
178
183
  params.set('parentUrl', window.location.href);
179
184
  }
180
- catch (_c) {
185
+ catch (_d) {
181
186
  // Ignore if can't access location
182
187
  }
183
188
  // Encode theme from collection
@@ -192,7 +197,7 @@ export class IframeResponder {
192
197
  params.set('theme', btoa(JSON.stringify(themeData)));
193
198
  }
194
199
  }
195
- catch (_d) {
200
+ catch (_e) {
196
201
  // Ignore encoding errors
197
202
  }
198
203
  }
@@ -210,7 +215,8 @@ export class IframeResponder {
210
215
  const path = this.options.initialPath.startsWith('/') ? this.options.initialPath : '/' + this.options.initialPath;
211
216
  // Insert path before the ?
212
217
  const [beforeHash, afterHash] = baseWithHash.split('#');
213
- finalUrl = `${beforeHash}#${afterHash || ''}${path}?${existingParams.toString()}`;
218
+ // App addresses end in "#/": join without doubling the slash ("#//my-bookings" matches no route).
219
+ finalUrl = `${beforeHash}#${(afterHash || '').replace(/\/+$/, '')}${path}?${existingParams.toString()}`;
214
220
  }
215
221
  else {
216
222
  finalUrl = `${baseWithHash}?${existingParams.toString()}`;
@@ -765,8 +771,12 @@ export function isAdminFromRoles(user, collection, proof) {
765
771
  * Standalone helper for cases where you don't need the full IframeResponder.
766
772
  */
767
773
  export function buildIframeSrc(options) {
768
- var _a, _b;
774
+ var _a, _b, _c;
769
775
  const params = new URLSearchParams();
776
+ for (const [key, value] of Object.entries((_a = options.params) !== null && _a !== void 0 ? _a : {})) {
777
+ if (value != null && value !== '')
778
+ params.set(key, String(value));
779
+ }
770
780
  params.set('collectionId', options.collectionId);
771
781
  params.set('appId', options.appId);
772
782
  if (options.productId)
@@ -776,14 +786,14 @@ export function buildIframeSrc(options) {
776
786
  if (options.isAdmin)
777
787
  params.set('isAdmin', 'true');
778
788
  params.set('dark', options.dark ? '1' : '0');
779
- if (((_a = options.theme) === null || _a === void 0 ? void 0 : _a.primary) || ((_b = options.theme) === null || _b === void 0 ? void 0 : _b.secondary)) {
789
+ if (((_b = options.theme) === null || _b === void 0 ? void 0 : _b.primary) || ((_c = options.theme) === null || _c === void 0 ? void 0 : _c.secondary)) {
780
790
  const themeData = { p: options.theme.primary, s: options.theme.secondary };
781
791
  params.set('theme', btoa(JSON.stringify(themeData)));
782
792
  }
783
793
  try {
784
794
  params.set('parentUrl', window.location.href);
785
795
  }
786
- catch (_c) {
796
+ catch (_d) {
787
797
  // Ignore
788
798
  }
789
799
  let base = options.appUrl.replace(/#\/?$/, '').replace(/\/$/, '');
package/dist/openapi.yaml CHANGED
@@ -19909,6 +19909,8 @@ components:
19909
19909
  DeepLinkEntry:
19910
19910
  type: object
19911
19911
  properties:
19912
+ id:
19913
+ type: string
19912
19914
  title:
19913
19915
  type: string
19914
19916
  path:
@@ -19917,6 +19919,8 @@ components:
19917
19919
  type: object
19918
19920
  additionalProperties:
19919
19921
  type: string
19922
+ accepts:
19923
+ $ref: "#/components/schemas/PublicViewParams"
19920
19924
  widget:
19921
19925
  type: object
19922
19926
  additionalProperties: true
@@ -27652,6 +27656,10 @@ components:
27652
27656
  type: string
27653
27657
  initialPath:
27654
27658
  type: string
27659
+ params:
27660
+ type: object
27661
+ additionalProperties:
27662
+ type: string
27655
27663
  isAdmin:
27656
27664
  type: boolean
27657
27665
  cache:
@@ -109,6 +109,12 @@ export interface AppContainerComponent {
109
109
  * { "title": "About Us", "params": { "pageId": "about-us" } }
110
110
  */
111
111
  export interface DeepLinkEntry {
112
+ /**
113
+ * Stable id for this page, unique within the app (optional). Hosts and websites refer to the page
114
+ * by it (e.g. a site embeds `{ app: 'appointments', page: 'book' }`), so a renamed `title` or a moved
115
+ * `path` doesn't break them.
116
+ */
117
+ id?: string;
112
118
  /** Human-readable label shown in menus and offered to AI agents */
113
119
  title: string;
114
120
  /**
@@ -123,6 +129,12 @@ export interface DeepLinkEntry {
123
129
  * those are injected by the platform automatically.
124
130
  */
125
131
  params?: Record<string, string>;
132
+ /**
133
+ * The params a host may supply when it opens this page (in addition to the platform's own), e.g. a
134
+ * booking page that can start on one service: `{ optional: ['service', 'staff', 'date'] }`. `params`
135
+ * above are the values this entry PINS; `accepts` are the ones the caller fills in.
136
+ */
137
+ accepts?: PublicViewParams;
126
138
  /**
127
139
  * When `true`, this entry is also available as a dynamic data context for widgets
128
140
  * (in addition to being a navigable page / container route).
@@ -856,10 +868,10 @@ export interface AppManifest {
856
868
  components: AppContainerComponent[];
857
869
  };
858
870
  /**
859
- * PORTAL deep-linkable states built into this app — the entry points the portal's menu system
860
- * (bottom menu, side menus, tabs) can link to. Use these when one app has several ways to enter/load
861
- * its portal component (e.g. a list view and a calendar view, or a viewer and an editor) that
862
- * different parts of portal should link to independently. These live INSIDE portal.
871
+ * The app's PAGES that a host opens — portal menus (bottom menu, side menus, tabs) and WEBSITES that
872
+ * embed the app (IframeResponder). Use these when one app has several ways in (a list view and a
873
+ * calendar view; book, upcoming bookings, change a booking). A host opens them with its own signed-in
874
+ * session: the page's API calls go through the host, so it acts as the person signed in there.
863
875
  * Fixed routes are declared here at build time; dynamic content entries (e.g. CMS pages) are stored
864
876
  * separately in `appConfig.linkable` — merge both for the full navigable set.
865
877
  * @see DeepLinkEntry
@@ -24,6 +24,12 @@ export interface IframeResponderOptions {
24
24
  appUrl?: string;
25
25
  /** Initial hash path (e.g., '/settings') */
26
26
  initialPath?: string;
27
+ /**
28
+ * The page's own params (a `linkable` entry's pinned `params` plus what it `accepts`), e.g.
29
+ * `{ service: 'svc_123' }`. Added to the app's URL alongside the platform's context params, which
30
+ * always win (collectionId, appId, productId, proofId, isAdmin, dark, theme, parentUrl).
31
+ */
32
+ params?: Record<string, string>;
27
33
  /** Is user an admin of this collection */
28
34
  isAdmin?: boolean;
29
35
  cache?: CachedData;
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.1.2 | Generated: 2026-10-26T14:58:53.408Z
3
+ Version: 2.1.3 | Generated: 2026-10-26T21:00:54.277Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -2585,9 +2585,11 @@ interface AppContainerComponent {
2585
2585
  **DeepLinkEntry** (interface)
2586
2586
  ```typescript
2587
2587
  interface DeepLinkEntry {
2588
+ id?: string;
2588
2589
  title: string;
2589
2590
  path?: string;
2590
2591
  params?: Record<string, string>;
2592
+ accepts?: PublicViewParams;
2591
2593
  widget?: true;
2592
2594
  }
2593
2595
  ```
@@ -7479,6 +7481,7 @@ interface IframeResponderOptions {
7479
7481
  version?: string;
7480
7482
  appUrl?: string;
7481
7483
  initialPath?: string;
7484
+ params?: Record<string, string>;
7482
7485
  isAdmin?: boolean;
7483
7486
  cache?: CachedData;
7484
7487
  onAuthLogin?: (
@@ -326,11 +326,28 @@ Static deep-linkable states built into the app — fixed routes that exist regar
326
326
 
327
327
  See the [Deep Link Discovery guide](deep-link-discovery.md) for the full dual-source pattern (static manifest routes + dynamic `appConfig.linkable`).
328
328
 
329
+ These are the app's **pages that a host opens**: portal menus and tabs, and websites that embed the app
330
+ (websites.md → "Using another app's pages"). A host opens them with its own signed-in session, so one
331
+ app can offer several pages that each know the visitor: book, upcoming bookings, past bookings, change a
332
+ booking.
333
+
334
+ ```json
335
+ "linkable": [
336
+ { "id": "book", "title": "Book an appointment", "path": "/",
337
+ "accepts": { "optional": ["service", "staff", "date"] } },
338
+ { "id": "upcoming", "title": "Your upcoming bookings", "path": "/my-bookings" },
339
+ { "id": "change", "title": "Change a booking", "path": "/booking",
340
+ "accepts": { "required": ["id"] } }
341
+ ]
342
+ ```
343
+
329
344
  | Field | Type | Required | Description |
330
345
  |-------|------|----------|-------------|
346
+ | `id` | string | ❌ | Stable id, unique within the app: hosts and sites refer to the page by it |
331
347
  | `title` | string | ✅ | Human-readable label shown in menus and offered to AI agents |
332
348
  | `path` | string | ❌ | Hash route within the app (defaults to `"/"` if omitted) |
333
- | `params` | object | ❌ | App-specific query params appended to the URL — do **not** include platform params (`collectionId`, `productId`, etc.) |
349
+ | `params` | object | ❌ | Params this entry PINS, appended to the URL — do **not** include platform params (`collectionId`, `productId`, etc.) |
350
+ | `accepts` | `{ required?: string[]; optional?: string[] }` | ❌ | The params a host may supply when it opens the page (e.g. which service to start on) |
334
351
 
335
352
  #### `publicViews`
336
353
 
@@ -371,7 +388,7 @@ An app can have any combination of three setup styles. Only public views are ext
371
388
  | Style | Declared by | Lives | Context |
372
389
  |-------|-------------|-------|---------|
373
390
  | **Portal components** — where the app renders inside portal (collection / product / batch / variant / proof) | module registry `components.*` (set at publish) | Inside portal | Physical twin (QR/NFC scan) |
374
- | **Portal deep links** — the entry points portal menus/tabs/side-menus link to (e.g. list view vs calendar view) | `linkable` / `DeepLinkEntry` | Inside portal | Portal (menu picks the entry) |
391
+ | **App pages** — the entry points portal menus/tabs link to and websites embed (e.g. list vs calendar; book vs my bookings) | `linkable` / `DeepLinkEntry` | Inside a host: portal or a website | The host: its signed-in session, plus the page's `accepts` params |
375
392
  | **Public views** — standalone external screens | `publicViews` (this block) | Outside portal | URL params only |
376
393
 
377
394
  #### `records`
@@ -172,6 +172,9 @@ Both sources use the same entry shape:
172
172
 
173
173
  ```typescript
174
174
  interface DeepLinkEntry {
175
+ /** Stable id, unique within the app (optional): hosts and websites refer to the page by it */
176
+ id?: string;
177
+
175
178
  /** Human-readable label for this state (required) */
176
179
  title: string;
177
180
 
@@ -193,6 +196,13 @@ interface DeepLinkEntry {
193
196
  */
194
197
  params?: Record<string, string>;
195
198
 
199
+ /**
200
+ * The params a host may supply when it opens this page (optional), e.g. a booking page that can
201
+ * start on one service: `{ optional: ['service', 'staff', 'date'] }`. `params` are pinned by the
202
+ * entry; `accepts` are filled in by whoever opens it.
203
+ */
204
+ accepts?: { required?: string[]; optional?: string[] };
205
+
196
206
  /**
197
207
  * When `true`, this entry is also available as a dynamic data context for widgets.
198
208
  *
@@ -211,7 +221,9 @@ interface DeepLinkEntry {
211
221
  |-------|----------|-------|
212
222
  | `title` | ✅ | Displayed in menus and offered to AI agents. Should be concise and human-readable. |
213
223
  | `path` | ❌ | Hash route within the app. Defaults to `/` if omitted. |
224
+ | `id` | ❌ | Stable id for hosts and websites to refer to the page by. |
214
225
  | `params` | ❌ | App-specific query params only. Platform params are injected automatically. |
226
+ | `accepts` | ❌ | The params whoever opens the page may supply (`required` / `optional`). |
215
227
  | `widget` | ❌ | Set to `true` to make this entry selectable in the widget config picker as a dynamic data context. |
216
228
 
217
229
  > **Tip:** Different entries can share the same `path` if they differ by `params` — for example, two entries pointing at `/settings` with different `tab` params.
@@ -103,6 +103,7 @@ interface IframeResponderOptions {
103
103
  version?: 'stable' | 'development'; // App version (default: 'stable')
104
104
  appUrl?: string; // Override URL (for local dev)
105
105
  initialPath?: string; // Initial hash path (e.g., '/settings')
106
+ params?: Record<string, string>; // The page's own params (e.g. { service: 'svc_123' }); context params win
106
107
 
107
108
  // Data
108
109
  cache?: CachedData; // Pre-cached data
package/docs/websites.md CHANGED
@@ -66,6 +66,32 @@ bytes. `_server/` is never served to visitors.
66
66
  doing work that belongs in a server function or a scheduled job.
67
67
  - **No secrets** in the server bundle and no Node built-ins beyond `nodejs_compat`.
68
68
 
69
+ ## Using another app's pages
70
+
71
+ Some apps do a job a site shouldn't rebuild: a booking journey holds the time rules, the clash
72
+ handling and the confirmation; "my bookings" holds who may change what. Those apps declare their pages
73
+ in `linkable` (app-manifest.md), each with a stable `id`, a `path` and the params it `accepts`. A site
74
+ embeds one with **`IframeResponder`** (iframe-responder.md), from the browser:
75
+
76
+ ```typescript
77
+ const site = SL.site.current()
78
+ const responder = new SL.IframeResponder({
79
+ collectionId: site.collectionId,
80
+ appId: 'appointments', // the app's id on this collection
81
+ initialPath: '/my-bookings', // the page's `path`
82
+ params: { service: 'svc_123' }, // what the page `accepts`
83
+ onResize: (h) => { iframe.style.height = `${h}px` },
84
+ })
85
+ iframe.src = await responder.attach(iframe)
86
+ ```
87
+
88
+ - **The visitor's session goes with it.** The page's API calls are proxied through the site, so it
89
+ acts as whoever is signed in to the site (or as a guest). Never pass a token in the URL.
90
+ - **The app must be installed** on the site's collection; its address comes from there.
91
+ - **Show the app's content natively where you can** (its `headless` data: services, staff, events)
92
+ for your own design and SEO, and embed the page only for the part that does the work.
93
+ - Pages render on the client, after load: they aren't part of the server-rendered HTML.
94
+
69
95
  ## Caching
70
96
 
71
97
  The router keeps a rendered page at the edge when your response says it may:
package/openapi.yaml CHANGED
@@ -19909,6 +19909,8 @@ components:
19909
19909
  DeepLinkEntry:
19910
19910
  type: object
19911
19911
  properties:
19912
+ id:
19913
+ type: string
19912
19914
  title:
19913
19915
  type: string
19914
19916
  path:
@@ -19917,6 +19919,8 @@ components:
19917
19919
  type: object
19918
19920
  additionalProperties:
19919
19921
  type: string
19922
+ accepts:
19923
+ $ref: "#/components/schemas/PublicViewParams"
19920
19924
  widget:
19921
19925
  type: object
19922
19926
  additionalProperties: true
@@ -27652,6 +27656,10 @@ components:
27652
27656
  type: string
27653
27657
  initialPath:
27654
27658
  type: string
27659
+ params:
27660
+ type: object
27661
+ additionalProperties:
27662
+ type: string
27655
27663
  isAdmin:
27656
27664
  type: boolean
27657
27665
  cache:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",