@proveanything/smartlinks 2.0.69 → 2.0.70
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/dist/api/authKit.d.ts +28 -4
- package/dist/api/authKit.js +35 -1
- package/dist/docs/API_SUMMARY.md +73 -11
- package/dist/docs/auth-kit.md +46 -5
- package/dist/docs/members.md +182 -0
- package/dist/docs/overview.md +476 -475
- package/dist/docs/server-functions.md +4 -1
- package/dist/openapi.yaml +201 -20
- package/dist/testing/index.js +1 -1
- package/dist/types/appManifest.d.ts +16 -4
- package/dist/types/authKit.d.ts +58 -7
- package/docs/API_SUMMARY.md +73 -11
- package/docs/auth-kit.md +46 -5
- package/docs/members.md +182 -0
- package/docs/overview.md +476 -475
- package/docs/server-functions.md +4 -1
- package/openapi.yaml +201 -20
- package/package.json +1 -1
package/dist/docs/overview.md
CHANGED
|
@@ -1,475 +1,476 @@
|
|
|
1
|
-
# SmartLinks Microapp Development Guide
|
|
2
|
-
|
|
3
|
-
> **Platform revision:** R5 · **SDK:** `@proveanything/smartlinks@^2` · React 19 · Vite 8 · Router 7 · Tailwind 4 · TS 6.
|
|
4
|
-
> The canonical version/host stack lives in [host-dependency-contract.md](host-dependency-contract.md).
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## What Is a SmartLinks Microapp?
|
|
9
|
-
|
|
10
|
-
SmartLinks connects **physical products to digital experiences**: each item has a digital identity — a **proof** — that a consumer reaches by scanning a QR / NFC tag, then claims and enriches over time. A **microapp** is a focused, embeddable React experience a brand adds to that product's digital life: product info, warranty registration, authenticity checks, manuals, competitions, loyalty, post-purchase support, and more.
|
|
11
|
-
|
|
12
|
-
Rather than baking every feature into the core platform, functionality is distributed across purpose-built apps, so a brand adds exactly the experiences its product needs. Each app:
|
|
13
|
-
|
|
14
|
-
- **Embeds** in the SmartLinks Portal (public) and Admin Console (management)
|
|
15
|
-
- **Shares context** through URL parameters (collection, product, proof)
|
|
16
|
-
- **Inherits identity** from the parent platform's auth
|
|
17
|
-
- **Adapts** to the brand's theme
|
|
18
|
-
- **Communicates** with the parent via postMessage for deep linking and navigation
|
|
19
|
-
|
|
20
|
-
### Deployment Modes
|
|
21
|
-
|
|
22
|
-
Each microapp can be consumed in one or more of the following ways:
|
|
23
|
-
|
|
24
|
-
| Mode | Description |
|
|
25
|
-
|------|-------------|
|
|
26
|
-
| **Container** | Full app in parent React tree. ~150 KB+ lazy-loaded. The primary consumer surface. |
|
|
27
|
-
| **Iframe App** | Full React app inside an iframe. Fallback when sandboxing is required; still the standard for setup admin screens. |
|
|
28
|
-
| **Widget** | Lightweight React component in parent tree. ~10 KB, loaded immediately alongside the page. |
|
|
29
|
-
| **Mobile Admin Container** | Separate bundle for in-the-field operator/admin workflows on mobile. Built independently; may use Capacitor, Preact, or any other runtime. |
|
|
30
|
-
| **Executor** | JS library, no UI. Programmatic config, SEO metadata, LLM content for AI/server. |
|
|
31
|
-
|
|
32
|
-
Widgets and containers run in the parent's React tree (not iframes). Mobile Admin Containers are a separate bundle loaded by a dedicated mobile shell (Capacitor or PWA). Executors have no UI — they expose functions that AI orchestrators and the server call directly.
|
|
33
|
-
|
|
34
|
-
> **Admin vs consumer:** Admin experiences always ship as a **separate bundle** (`mobileAdmin` or iframe). The `containers` bundle is for consumer-facing surfaces only.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## SDK Documentation Reference
|
|
39
|
-
|
|
40
|
-
The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive documentation in `node_modules/@proveanything/smartlinks/docs/`. **Always read these files for detailed implementation guidance.**
|
|
41
|
-
|
|
42
|
-
> Product endpoints: use `products` (plural) for new integrations. The older `product` (singular) namespace remains for backward compatibility and is deprecated.
|
|
43
|
-
|
|
44
|
-
> **SDK baseline: `@proveanything/smartlinks@^2.0`** (R5). Install/update with `npm install @proveanything/smartlinks@^2.0`. Individual features may need a higher minor — see the relevant doc. The single source of truth for the R5 host/version stack is [`host-dependency-contract.md`](host-dependency-contract.md).
|
|
45
|
-
|
|
46
|
-
| Topic | File | When to Use |
|
|
47
|
-
|-------|------|-------------|
|
|
48
|
-
| **API Reference** | `docs/API_SUMMARY.md` | Complete SDK function reference, types, error handling |
|
|
49
|
-
| **Assets** | `docs/assets.md` | Asset object, AssetRef, upload, replace, soft-delete, restore, bulk-delete, public token-based uploads |
|
|
50
|
-
| **Building React Components** | `docs/building-react-components.md` | **READ THIS FIRST** — Dual-mode rendering, router rules, useAppContext pattern |
|
|
51
|
-
| **Multi-Page Architecture** | `docs/mpa.md` | Build pipeline, entry points, multi-page setup, content hashing |
|
|
52
|
-
| **AI & Chat** | `docs/ai.md` | Chat completions, RAG, streaming, tool calling, voice, podcasts, TTS |
|
|
53
|
-
| **Analytics** | `docs/analytics.md` | Fire-and-forget page/click/tag analytics plus admin dashboard queries |
|
|
54
|
-
| **Translations** | `docs/translations.md` | Runtime translation lookup, local-first IndexedDB caching, and translation admin APIs |
|
|
55
|
-
| **Theming** | `docs/theme.system.md` | Implementing dynamic themes via URL params or postMessage |
|
|
56
|
-
| **Theme Defaults** | `docs/theme-defaults.md` | Default colour values for light/dark modes |
|
|
57
|
-
| **Internationalization** | `docs/i18n.md` | Adding multi-language support, translation patterns |
|
|
58
|
-
| **Widgets** | `docs/widgets.md` | Building widgets, shared deps contract, settings schema |
|
|
59
|
-
| **Containers** | `docs/containers.md` | Building full-app embeddable containers (lazy-loaded) |
|
|
60
|
-
| **Mobile Admin Container** | `docs/mobile-admin-container.md` | Building a separate Capacitor-aware mobile admin bundle for field operators |
|
|
61
|
-
| **Executors** | `docs/executor.md` | Building executor bundles for SEO, LLM content, programmatic config |
|
|
62
|
-
| **Server Functions** | `docs/server-functions.md` | App-authored server-side functions `(ctx, event) ⇒ result`: security model, runtime surface, invoking |
|
|
63
|
-
| **Agent Tools** | `docs/agent-tools.md` | Exposing your app's actions to the SmartLinks agent — an MCP facade over server functions; **opt-in per app, additive, no migration**; complements `app.admin.json` (functions serve/adapt it, don't replace it); live loop staged |
|
|
64
|
-
| **Deploying & Registering** | `docs/deploying-apps.md` | Getting your app into the platform: fast dev publish, channels, deploy keys, registering releases |
|
|
65
|
-
| **Host Dependency Contract (R5)** | `docs/host-dependency-contract.md` | The libraries the host provides (React 19, Router 7, Radix, liquidjs, …), the externalise-don't-bundle rule + Vite config, and React-18 backwards-compat |
|
|
66
|
-
| **CSS Baseline** (`sl-baseline` v1) | `docs/css-baseline.md` | A small, frozen, `sl-`-namespaced set of structural helpers (layout, spacing, responsive flow, type scale, motion) the SDK ships (`@proveanything/smartlinks/baseline.css`) and the host guarantees — a teachable floor for apps + AI content. No colours/fonts/components. Opt-in via `meta.cssBaseline` |
|
|
67
|
-
| **Deep Linking** | `docs/deep-link-discovery.md` | URL state management, navigable states, portal menus, AI nav |
|
|
68
|
-
| **Portal Back Button** | `docs/portal-back-button.md` | Hierarchy-aware "up" navigation inside embedded apps |
|
|
69
|
-
| **Portal Request Action** | `docs/portal-request-action.md` | Triggering portal built-in actions (__qrScanner, __share, __logout, etc.) from sub-apps |
|
|
70
|
-
| **Interactions** | `docs/interactions.md` | Business events, outcomes, voting, competitions, and journey triggers |
|
|
71
|
-
| **App Config Files** | `docs/app-manifest.md` | Full field-by-field reference for both JSON config files |
|
|
72
|
-
| **Admin cards** | `docs/admin-cards.md` | Cards on the collection's dashboard in Studio: declare a card + an admin function returning its data; cached, refreshed only when its data changes |
|
|
73
|
-
| **Realtime** | `docs/realtime.md` | Live updates: change events (refetch when something changes) and declared app channels (a draw, a status) — no provider library or keys |
|
|
74
|
-
| **Liquid Templates** | `docs/liquid-templates.md` | Dynamic content rendering with LiquidJS |
|
|
75
|
-
| **Iframe Responder** | `docs/iframe-responder.md` | Iframe communication and proxy mode internals |
|
|
76
|
-
| **AI Guide Template** | `docs/ai-guide-template.md` | Template for creating `public/ai-guide.md` — customise per app |
|
|
77
|
-
| **Forms** | `docs/forms.md` | Form definitions, schema-driven rendering, submission patterns |
|
|
78
|
-
| **Auth Kit** | `docs/auth-kit.md` | End-user sign-in: email/password, magic links, phone OTP, Google OAuth |
|
|
79
|
-
| **
|
|
80
|
-
| **Portal
|
|
81
|
-
| **
|
|
82
|
-
| **
|
|
83
|
-
| **
|
|
84
|
-
| **
|
|
85
|
-
| **Proof
|
|
86
|
-
| **Proof
|
|
87
|
-
| **Proof
|
|
88
|
-
| **
|
|
89
|
-
| **
|
|
90
|
-
| **App
|
|
91
|
-
| **
|
|
92
|
-
| **
|
|
93
|
-
| **
|
|
94
|
-
| **
|
|
95
|
-
| **
|
|
96
|
-
| **
|
|
97
|
-
| **
|
|
98
|
-
| **
|
|
99
|
-
| **
|
|
100
|
-
| **
|
|
101
|
-
| **
|
|
102
|
-
| **
|
|
103
|
-
| **
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
- **
|
|
111
|
-
- **
|
|
112
|
-
- **
|
|
113
|
-
- **
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
>
|
|
117
|
-
>
|
|
118
|
-
>
|
|
119
|
-
>
|
|
120
|
-
>
|
|
121
|
-
>
|
|
122
|
-
>
|
|
123
|
-
|
|
124
|
-
- **
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
| **
|
|
141
|
-
| **
|
|
142
|
-
| **
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
|
169
|
-
| Write
|
|
170
|
-
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
- It
|
|
198
|
-
- It
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
| **
|
|
225
|
-
| **
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
- `.
|
|
263
|
-
- `.
|
|
264
|
-
- `.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
- **
|
|
306
|
-
- **
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
- **
|
|
312
|
-
- **
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
- `
|
|
357
|
-
- `
|
|
358
|
-
- `
|
|
359
|
-
- `
|
|
360
|
-
- `
|
|
361
|
-
- `
|
|
362
|
-
- `
|
|
363
|
-
- `
|
|
364
|
-
- `
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
├──
|
|
373
|
-
├──
|
|
374
|
-
|
|
375
|
-
│ ├── app.
|
|
376
|
-
│
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
│ ├──
|
|
380
|
-
│ ├──
|
|
381
|
-
│ ├──
|
|
382
|
-
│ ├──
|
|
383
|
-
│ ├──
|
|
384
|
-
│ ├──
|
|
385
|
-
│ ├──
|
|
386
|
-
│ ├──
|
|
387
|
-
│ ├──
|
|
388
|
-
│
|
|
389
|
-
│ │ ├──
|
|
390
|
-
│ │
|
|
391
|
-
│
|
|
392
|
-
│
|
|
393
|
-
│
|
|
394
|
-
│
|
|
395
|
-
|
|
396
|
-
├── vite.config.
|
|
397
|
-
├── vite.config.
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
const {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
1
|
+
# SmartLinks Microapp Development Guide
|
|
2
|
+
|
|
3
|
+
> **Platform revision:** R5 · **SDK:** `@proveanything/smartlinks@^2` · React 19 · Vite 8 · Router 7 · Tailwind 4 · TS 6.
|
|
4
|
+
> The canonical version/host stack lives in [host-dependency-contract.md](host-dependency-contract.md).
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## What Is a SmartLinks Microapp?
|
|
9
|
+
|
|
10
|
+
SmartLinks connects **physical products to digital experiences**: each item has a digital identity — a **proof** — that a consumer reaches by scanning a QR / NFC tag, then claims and enriches over time. A **microapp** is a focused, embeddable React experience a brand adds to that product's digital life: product info, warranty registration, authenticity checks, manuals, competitions, loyalty, post-purchase support, and more.
|
|
11
|
+
|
|
12
|
+
Rather than baking every feature into the core platform, functionality is distributed across purpose-built apps, so a brand adds exactly the experiences its product needs. Each app:
|
|
13
|
+
|
|
14
|
+
- **Embeds** in the SmartLinks Portal (public) and Admin Console (management)
|
|
15
|
+
- **Shares context** through URL parameters (collection, product, proof)
|
|
16
|
+
- **Inherits identity** from the parent platform's auth
|
|
17
|
+
- **Adapts** to the brand's theme
|
|
18
|
+
- **Communicates** with the parent via postMessage for deep linking and navigation
|
|
19
|
+
|
|
20
|
+
### Deployment Modes
|
|
21
|
+
|
|
22
|
+
Each microapp can be consumed in one or more of the following ways:
|
|
23
|
+
|
|
24
|
+
| Mode | Description |
|
|
25
|
+
|------|-------------|
|
|
26
|
+
| **Container** | Full app in parent React tree. ~150 KB+ lazy-loaded. The primary consumer surface. |
|
|
27
|
+
| **Iframe App** | Full React app inside an iframe. Fallback when sandboxing is required; still the standard for setup admin screens. |
|
|
28
|
+
| **Widget** | Lightweight React component in parent tree. ~10 KB, loaded immediately alongside the page. |
|
|
29
|
+
| **Mobile Admin Container** | Separate bundle for in-the-field operator/admin workflows on mobile. Built independently; may use Capacitor, Preact, or any other runtime. |
|
|
30
|
+
| **Executor** | JS library, no UI. Programmatic config, SEO metadata, LLM content for AI/server. |
|
|
31
|
+
|
|
32
|
+
Widgets and containers run in the parent's React tree (not iframes). Mobile Admin Containers are a separate bundle loaded by a dedicated mobile shell (Capacitor or PWA). Executors have no UI — they expose functions that AI orchestrators and the server call directly.
|
|
33
|
+
|
|
34
|
+
> **Admin vs consumer:** Admin experiences always ship as a **separate bundle** (`mobileAdmin` or iframe). The `containers` bundle is for consumer-facing surfaces only.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## SDK Documentation Reference
|
|
39
|
+
|
|
40
|
+
The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive documentation in `node_modules/@proveanything/smartlinks/docs/`. **Always read these files for detailed implementation guidance.**
|
|
41
|
+
|
|
42
|
+
> Product endpoints: use `products` (plural) for new integrations. The older `product` (singular) namespace remains for backward compatibility and is deprecated.
|
|
43
|
+
|
|
44
|
+
> **SDK baseline: `@proveanything/smartlinks@^2.0`** (R5). Install/update with `npm install @proveanything/smartlinks@^2.0`. Individual features may need a higher minor — see the relevant doc. The single source of truth for the R5 host/version stack is [`host-dependency-contract.md`](host-dependency-contract.md).
|
|
45
|
+
|
|
46
|
+
| Topic | File | When to Use |
|
|
47
|
+
|-------|------|-------------|
|
|
48
|
+
| **API Reference** | `docs/API_SUMMARY.md` | Complete SDK function reference, types, error handling |
|
|
49
|
+
| **Assets** | `docs/assets.md` | Asset object, AssetRef, upload, replace, soft-delete, restore, bulk-delete, public token-based uploads |
|
|
50
|
+
| **Building React Components** | `docs/building-react-components.md` | **READ THIS FIRST** — Dual-mode rendering, router rules, useAppContext pattern |
|
|
51
|
+
| **Multi-Page Architecture** | `docs/mpa.md` | Build pipeline, entry points, multi-page setup, content hashing |
|
|
52
|
+
| **AI & Chat** | `docs/ai.md` | Chat completions, RAG, streaming, tool calling, voice, podcasts, TTS |
|
|
53
|
+
| **Analytics** | `docs/analytics.md` | Fire-and-forget page/click/tag analytics plus admin dashboard queries |
|
|
54
|
+
| **Translations** | `docs/translations.md` | Runtime translation lookup, local-first IndexedDB caching, and translation admin APIs |
|
|
55
|
+
| **Theming** | `docs/theme.system.md` | Implementing dynamic themes via URL params or postMessage |
|
|
56
|
+
| **Theme Defaults** | `docs/theme-defaults.md` | Default colour values for light/dark modes |
|
|
57
|
+
| **Internationalization** | `docs/i18n.md` | Adding multi-language support, translation patterns |
|
|
58
|
+
| **Widgets** | `docs/widgets.md` | Building widgets, shared deps contract, settings schema |
|
|
59
|
+
| **Containers** | `docs/containers.md` | Building full-app embeddable containers (lazy-loaded) |
|
|
60
|
+
| **Mobile Admin Container** | `docs/mobile-admin-container.md` | Building a separate Capacitor-aware mobile admin bundle for field operators |
|
|
61
|
+
| **Executors** | `docs/executor.md` | Building executor bundles for SEO, LLM content, programmatic config |
|
|
62
|
+
| **Server Functions** | `docs/server-functions.md` | App-authored server-side functions `(ctx, event) ⇒ result`: security model, runtime surface, invoking |
|
|
63
|
+
| **Agent Tools** | `docs/agent-tools.md` | Exposing your app's actions to the SmartLinks agent — an MCP facade over server functions; **opt-in per app, additive, no migration**; complements `app.admin.json` (functions serve/adapt it, don't replace it); live loop staged |
|
|
64
|
+
| **Deploying & Registering** | `docs/deploying-apps.md` | Getting your app into the platform: fast dev publish, channels, deploy keys, registering releases |
|
|
65
|
+
| **Host Dependency Contract (R5)** | `docs/host-dependency-contract.md` | The libraries the host provides (React 19, Router 7, Radix, liquidjs, …), the externalise-don't-bundle rule + Vite config, and React-18 backwards-compat |
|
|
66
|
+
| **CSS Baseline** (`sl-baseline` v1) | `docs/css-baseline.md` | A small, frozen, `sl-`-namespaced set of structural helpers (layout, spacing, responsive flow, type scale, motion) the SDK ships (`@proveanything/smartlinks/baseline.css`) and the host guarantees — a teachable floor for apps + AI content. No colours/fonts/components. Opt-in via `meta.cssBaseline` |
|
|
67
|
+
| **Deep Linking** | `docs/deep-link-discovery.md` | URL state management, navigable states, portal menus, AI nav |
|
|
68
|
+
| **Portal Back Button** | `docs/portal-back-button.md` | Hierarchy-aware "up" navigation inside embedded apps |
|
|
69
|
+
| **Portal Request Action** | `docs/portal-request-action.md` | Triggering portal built-in actions (__qrScanner, __share, __logout, etc.) from sub-apps |
|
|
70
|
+
| **Interactions** | `docs/interactions.md` | Business events, outcomes, voting, competitions, and journey triggers |
|
|
71
|
+
| **App Config Files** | `docs/app-manifest.md` | Full field-by-field reference for both JSON config files |
|
|
72
|
+
| **Admin cards** | `docs/admin-cards.md` | Cards on the collection's dashboard in Studio: declare a card + an admin function returning its data; cached, refreshed only when its data changes |
|
|
73
|
+
| **Realtime** | `docs/realtime.md` | Live updates: change events (refetch when something changes) and declared app channels (a draw, a status) — no provider library or keys |
|
|
74
|
+
| **Liquid Templates** | `docs/liquid-templates.md` | Dynamic content rendering with LiquidJS |
|
|
75
|
+
| **Iframe Responder** | `docs/iframe-responder.md` | Iframe communication and proxy mode internals |
|
|
76
|
+
| **AI Guide Template** | `docs/ai-guide-template.md` | Template for creating `public/ai-guide.md` — customise per app |
|
|
77
|
+
| **Forms** | `docs/forms.md` | Form definitions, schema-driven rendering, submission patterns |
|
|
78
|
+
| **Auth Kit** | `docs/auth-kit.md` | End-user sign-in: email/password, magic links, phone OTP, Google OAuth |
|
|
79
|
+
| **Members** | `docs/members.md` | Signed-in members with a level (clubs, leagues, members' areas): the level field, members-only functions, joining rules |
|
|
80
|
+
| **Portal Request Login** | `docs/portal-request-login.md` | How sub-apps ask the portal to authenticate the user; hook and iframe postMessage contracts |
|
|
81
|
+
| **Portal Auth Broadcast** | `docs/portal-auth-broadcast.md` | Publishing custom auth flows to the portal; syncing sessions across containers and iframes |
|
|
82
|
+
| **Contact Search** | `docs/contact-search.md` | Admin contact search: free-text, typeahead, identity/tag/JSONB filters, and pagination |
|
|
83
|
+
| **App Records Pattern** | `docs/app-records-pattern.md` | Standard pattern for per-product/facet/variant/batch admin + public widget UIs |
|
|
84
|
+
| **UI Utils** | `docs/ui-utils.md` | `@proveanything/smartlinks-utils-ui` — React shells, hooks, and primitives for records-based apps |
|
|
85
|
+
| **Product/Proof Data Scoping** | `docs/proof-product-data-scoping.md` | Canonical spec for `product.data`/`.admin` and `proof.data`/`.admin`/`.values` (owner/personal) — who can read and write each bucket |
|
|
86
|
+
| **Proof Claiming** | `docs/proof-claiming-methods.md` | The ways a user claims a proof (serial, NFC, claim-set, auto-generate) |
|
|
87
|
+
| **Proof Share Grants** | `docs/proof-share-grants.md` | Delegated, scoped, revocable bearer access to a single proof (read/comment/verify-owner) |
|
|
88
|
+
| **Proof Ownership Transfer** | `docs/proof-ownership-transfer.md` | Moving a proof's single owner (directed transfer / open release), accept/cancel, and the state machine |
|
|
89
|
+
| **appConfig / Feature Flags** | `docs/appConfig.md` | `appConfig` settings contract — installed apps, `system.features`/`entitledAppGroups`/`meters`, `isFeatureEnabled()` helper |
|
|
90
|
+
| **App Objects** | `docs/app-objects.md` | Queryable domain objects — `app.records` / `app.cases` / `app.threads`: JSONB zones, visibility, policies, aggregations |
|
|
91
|
+
| **App Data Storage** | `docs/app-data-storage.md` | Decision guide: pick between `appConfiguration` / `userAppData` / `app.records` |
|
|
92
|
+
| **Attestations** | `docs/attestations.md` | Postgres attestations API (proof-level user/admin data; replaces the legacy Firestore path) |
|
|
93
|
+
| **Caching** | `docs/caching.md` | SDK GET cache tiers + TTLs, `invalidateCache({ exact })`, and `force`/push guidance |
|
|
94
|
+
| **Comms & Broadcasts** | `docs/comms.md` | Transactional comms, campaigns, consent, push |
|
|
95
|
+
| **Container Tracking** | `docs/container-tracking.md` | Physical/logical **item** container groupings — *not* app containers (see containers.md) |
|
|
96
|
+
| **Lots** | `docs/lots.md` | Cross-SKU production "Lot" entity |
|
|
97
|
+
| **Loyalty** | `docs/loyalty.md` | Points, members, earning rules |
|
|
98
|
+
| **Integrations** | `docs/integrations.md` | Inbound/outbound external-system integration flows |
|
|
99
|
+
| **Connectors** | `docs/connectors.md` | Connector apps: the manifest `connector` block + the functions the integration engine calls |
|
|
100
|
+
| **Item Context** | `docs/item-context.md` | The `itemContext` container prop (serial / NFC authenticity context) |
|
|
101
|
+
| **Native Facade** | `docs/native-facade.md` | `host.native` / `SL.native` device-capability facade |
|
|
102
|
+
| **Product Facets** | `docs/PRODUCT_FACETS_SDK.md` | Facet API reference (admin + public endpoints, types) |
|
|
103
|
+
| **AI Tools & Skills** | `docs/ai-tools-and-skills.md` | Platform AI capability registry (web research, extraction, images) |
|
|
104
|
+
| **Proof Comms Triggers** | `docs/proof-comms-triggers.md` | Transactional comms fired as a side-effect of proof actions |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Technical Overview
|
|
109
|
+
|
|
110
|
+
- **Iframe-based** — Apps run inside iframes in both the public Portal and Admin Console
|
|
111
|
+
- **Hash routing** — Uses `/#/` routes for iframe compatibility (e.g., `/#/`, `/#/admin`)
|
|
112
|
+
- **Context via URL params** — All contextual data is passed through URL parameters
|
|
113
|
+
- **SmartLinks NPM module** — All data access and platform interaction goes through `@proveanything/smartlinks`
|
|
114
|
+
- **No standalone auth** — Authentication is handled by the parent SmartLinks platform
|
|
115
|
+
|
|
116
|
+
> **Use the host-provided `SL`, don't instantiate your own.** When your app runs in a
|
|
117
|
+
> container/iframe, the host injects an already-initialized, authenticated SDK instance (the
|
|
118
|
+
> `SL` prop / the externalized `@proveanything/smartlinks` singleton). Import and use *that*.
|
|
119
|
+
> Calling `initializeApi()` yourself to spin up a **second** SDK instance is a common source
|
|
120
|
+
> of bugs: it won't share the host's auth (so it looks signed-out), won't share the host's
|
|
121
|
+
> cache (duplicate requests, stale data), and in proxy mode it bypasses the host's request
|
|
122
|
+
> routing. Rule of thumb: **host-provided `SL` for anything the platform owns** (auth, config,
|
|
123
|
+
> data, cache); only app-owned state is yours.
|
|
124
|
+
- **Multi-page build** — Separate bundles for public and admin — see `docs/mpa.md`
|
|
125
|
+
- **Embedded back navigation** — Use `docs/portal-back-button.md` when a sub-app has a real content hierarchy
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Data Model Hierarchy
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
Collection (Business/Brand)
|
|
133
|
+
└── Product (Product Type/Definition)
|
|
134
|
+
└── Proof (Specific Instance with Owner)
|
|
135
|
+
└── Attestation (User/Admin Data on Proof)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
| Entity | Description | Example |
|
|
139
|
+
|--------|-------------|---------|
|
|
140
|
+
| **Collection** | Top-level container representing a business or brand | "Acme Wine Co." |
|
|
141
|
+
| **Product** | A type of product (not a specific item) | "2023 Cabernet Sauvignon" |
|
|
142
|
+
| **Proof** | A specific instance of a product, often with an owner | Bottle #12345 claimed by user@email.com |
|
|
143
|
+
| **Attestation** | Data attached to a proof by users or admins | Warranty registration, tasting notes |
|
|
144
|
+
|
|
145
|
+
### URL Parameters
|
|
146
|
+
|
|
147
|
+
| Parameter | Type | Description |
|
|
148
|
+
|-----------|------|-------------|
|
|
149
|
+
| `collectionId` | string | The collection being viewed/managed |
|
|
150
|
+
| `productId` | string | The specific product (within collection) |
|
|
151
|
+
| `proofId` | string | The specific proof instance |
|
|
152
|
+
| `appId` | string | This app's unique identifier (for data scoping) |
|
|
153
|
+
| `dark` | `1` or `0` | Whether to use dark mode |
|
|
154
|
+
| `theme` | base64 | Full theme configuration (see `docs/theme.system.md`) |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Authentication & Permissions
|
|
159
|
+
|
|
160
|
+
SmartLinks apps do **not** implement their own authentication. The parent platform handles all auth:
|
|
161
|
+
|
|
162
|
+
- Use `SL.auth.getAccount()` to check if a user is logged in
|
|
163
|
+
- The response includes whether the user is an `admin` or regular user
|
|
164
|
+
- Many SmartLinks API functions behave differently based on admin status
|
|
165
|
+
|
|
166
|
+
| Capability | Admin | Regular User |
|
|
167
|
+
|------------|-------|-------------|
|
|
168
|
+
| Read collection/product data | ✅ | ✅ |
|
|
169
|
+
| Write app configuration | ✅ | ❌ |
|
|
170
|
+
| Write attestations | ✅ | ✅ (own proofs only) |
|
|
171
|
+
| Access admin-only API fields | ✅ | ❌ |
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Data Storage Patterns
|
|
176
|
+
|
|
177
|
+
### ⚠️ Critical: Admin Mode Flag
|
|
178
|
+
|
|
179
|
+
**When building admin interfaces, you MUST pass `admin: true` in API options.**
|
|
180
|
+
|
|
181
|
+
Without this flag, API calls use the public endpoint and will fail to write data:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// ❌ WRONG — will fail in admin interface
|
|
185
|
+
await SL.appConfiguration.setConfig({ collectionId, appId, config: myConfig });
|
|
186
|
+
|
|
187
|
+
// ✅ CORRECT — include admin: true
|
|
188
|
+
await SL.appConfiguration.setConfig({ collectionId, appId, config: myConfig, admin: true });
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
This applies to all write operations: `setConfig`, `setDataItem`, `updateDataItem`, etc.
|
|
192
|
+
|
|
193
|
+
### Endpoint Auth vs Data Visibility
|
|
194
|
+
|
|
195
|
+
`admin: true` is an endpoint selector, not a privacy marker.
|
|
196
|
+
|
|
197
|
+
- It tells the SDK to call the admin endpoint.
|
|
198
|
+
- It allows writes and admin reads.
|
|
199
|
+
- It does **not** mean every root-level field you save becomes admin-only.
|
|
200
|
+
|
|
201
|
+
For `appConfiguration` config blobs and `collection.getSettings()` groups, root-level fields are typically the public-facing settings. If you need private values such as tokens or secrets, store them inside a top-level `admin` object:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
await SL.appConfiguration.setConfig({
|
|
205
|
+
collectionId,
|
|
206
|
+
appId,
|
|
207
|
+
admin: true,
|
|
208
|
+
config: {
|
|
209
|
+
publicLabel: 'Warranty Portal',
|
|
210
|
+
color: '#B68C2A',
|
|
211
|
+
admin: {
|
|
212
|
+
accessToken: 'secret-token'
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
})
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Public reads omit the `admin` block. Admin reads include it.
|
|
219
|
+
|
|
220
|
+
### Config vs Data
|
|
221
|
+
|
|
222
|
+
| Storage Type | Function | Use Case |
|
|
223
|
+
|-------------|---------|---------|
|
|
224
|
+
| **Config** (`getConfig`/`setConfig`) | Single JSON document | App settings, feature flags, global options |
|
|
225
|
+
| **Data** (`getData`/`setDataItem`) | Array of documents with IDs | Lists of items, records, entries |
|
|
226
|
+
| **App Objects** (`app.records` / `app.cases` / `app.threads`) | Queryable domain objects | Real app entities, workflows, conversations, richer access control |
|
|
227
|
+
|
|
228
|
+
Both can be scoped to **collection level** or **product level** by including `productId`.
|
|
229
|
+
|
|
230
|
+
For config/settings visibility, remember: root fields are the normal shared payload, while a reserved top-level `admin` object is the place for admin-only values.
|
|
231
|
+
|
|
232
|
+
Prefer `app.records` over `setDataItem` when the data is becoming a real entity that needs lifecycle, ownership, visibility, relationships, or filtering. Keep `setDataItem` for simple keyed scoped documents and config-adjacent content.
|
|
233
|
+
|
|
234
|
+
### Feature Flags & Entitlements (`appConfig`)
|
|
235
|
+
|
|
236
|
+
The platform-owned `appConfig` settings group (`system.features`, `system.meters`, `system.entitledAppGroups`, installed `apps[]`) tells a microapp what's installed and entitled for a collection. Use `SL.appConfiguration.isFeatureEnabled(collectionId, flag)` to gate a feature — it's the standard, cache-backed way to do this rather than hand-rolling a `getConfig` call:
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
if (await SL.appConfiguration.isFeatureEnabled(collectionId, 'custom_domain')) {
|
|
240
|
+
enableCustomDomainUI();
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
It's async (the first check for a collection has nothing cached yet); `SL.appConfiguration.isFeatureEnabledSync()` gives a synchronous, cache-only read (`boolean | undefined`) for callers that warmed the cache earlier and can't await. See `docs/appConfig.md` for the full contract, including `systemPrivate` (admin-only overrides, always stripped for non-admin reads).
|
|
245
|
+
|
|
246
|
+
### Attestations (Proof-level data)
|
|
247
|
+
|
|
248
|
+
For data attached to specific proof instances, use `SL.attestation.create()` and `SL.attestation.list()`.
|
|
249
|
+
|
|
250
|
+
### Custom Data Scoping (Product & Proof)
|
|
251
|
+
|
|
252
|
+
`product.data`/`product.admin` and `proof.data`/`proof.admin`/`proof.values` are the canonical buckets for custom fields on products and proofs — `data` is public and business-writable, `admin` is business-only, and `proof.values` additionally supports owner-scoped (`values.owner`) and per-user (`values.personal[userId]`) sub-keys. This is a different mechanism from the app-scoped storage in `docs/app-data-storage.md` (which is for app-owned config/records, not the product/proof documents themselves).
|
|
253
|
+
|
|
254
|
+
See `docs/proof-product-data-scoping.md` for the full read/write authority matrix, worked examples, and the `productFields`/`proofFields` collection-settings schemas that drive field-config editors.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Error Handling
|
|
259
|
+
|
|
260
|
+
The SmartLinks SDK returns structured `SmartlinksApiError` objects. Use `instanceof SmartlinksApiError` to access `.statusCode`, `.message`, and helper methods:
|
|
261
|
+
|
|
262
|
+
- `.isAuthError()` — 401/403 responses
|
|
263
|
+
- `.isNotFound()` — 404 responses
|
|
264
|
+
- `.isRateLimited()` — 429 responses
|
|
265
|
+
- `.isServerError()` — 5xx responses
|
|
266
|
+
|
|
267
|
+
See `docs/API_SUMMARY.md` for complete error handling documentation.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## AI Integration
|
|
272
|
+
|
|
273
|
+
SmartLinks provides comprehensive AI capabilities through the `SL.ai` namespace. **Always use SmartLinks AI for microapps** — do not integrate external AI services (OpenAI, Anthropic, Lovable Cloud AI, etc.) directly.
|
|
274
|
+
|
|
275
|
+
Key capabilities: chat completions (streaming + tool calling), RAG document Q&A, voice input/output, podcast generation, text-to-speech, model listing.
|
|
276
|
+
|
|
277
|
+
See `docs/ai.md` for complete documentation.
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Interactions & Event Tracking
|
|
282
|
+
|
|
283
|
+
The `SL.interactions` namespace tracks user engagement — competition entries, votes, form submissions, warranty registrations. Events can trigger automated journeys and communications.
|
|
284
|
+
|
|
285
|
+
**The one rule:** you never choose an interaction id. In admin, `SL.interactions.ensureType(collectionId, { appId, key: 'vote', … })` finds-or-creates the type and returns its server-minted `id`; store it in app config (`interactionIds: { vote: type.id }`); everywhere else — public widgets included — read `interactionIds.vote` from config and pass that as `interactionId`. Never write an interactionId as a string literal.
|
|
286
|
+
|
|
287
|
+
Key functions: `submitPublicEvent()`, `appendEvent()` (admin), `countsByOutcome()`, `query()`.
|
|
288
|
+
|
|
289
|
+
See `docs/interactions.md` for complete documentation.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Liquid Templating
|
|
294
|
+
|
|
295
|
+
Use the `<LiquidContent>` component, `useLiquidTemplate` hook, and `renderLiquid` utility for admin-configured dynamic content using Liquid syntax.
|
|
296
|
+
|
|
297
|
+
See `docs/liquid-templates.md` for full context variables, filters, and examples.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Design Principles
|
|
302
|
+
|
|
303
|
+
### Public Interface (Portal)
|
|
304
|
+
|
|
305
|
+
- **Mobile-first** — Assume users are on phones
|
|
306
|
+
- **Non-technical** — Never show raw IDs or technical data
|
|
307
|
+
- **Accessible** — Follow WCAG guidelines
|
|
308
|
+
|
|
309
|
+
### Admin Interface
|
|
310
|
+
|
|
311
|
+
- **Feature-rich** — Power users expect advanced controls
|
|
312
|
+
- **Efficient** — Minimise clicks for common tasks
|
|
313
|
+
- **Desktop-optimised** — Admins typically use desktop browsers
|
|
314
|
+
|
|
315
|
+
### Theming
|
|
316
|
+
|
|
317
|
+
Apps receive theme configuration from the parent platform via URL parameter (`?theme=base64…`) and PostMessage updates. See `docs/theme.system.md`.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Common Hooks
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
// Fetch collection/product/proof data
|
|
325
|
+
useCollectionData(collectionId)
|
|
326
|
+
useProductData(collectionId, productId)
|
|
327
|
+
useProofData(collectionId, productId, proofId)
|
|
328
|
+
|
|
329
|
+
// Fetch app configuration
|
|
330
|
+
useCollectionAppConfig(collectionId, appId)
|
|
331
|
+
useProductAppConfig(collectionId, productId, appId)
|
|
332
|
+
|
|
333
|
+
// Fetch app data (array of items)
|
|
334
|
+
useCollectionAppData(collectionId, appId)
|
|
335
|
+
useProductAppData(collectionId, productId, appId)
|
|
336
|
+
|
|
337
|
+
// Fetch attestations
|
|
338
|
+
useAttestationsData(collectionId, productId, proofId)
|
|
339
|
+
|
|
340
|
+
// URL parameter management
|
|
341
|
+
usePersistentQueryParams()
|
|
342
|
+
|
|
343
|
+
// Theme management
|
|
344
|
+
useSmartLinksTheme()
|
|
345
|
+
|
|
346
|
+
// Liquid templating
|
|
347
|
+
useLiquidTemplate(templateString, contextData)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## API Namespaces
|
|
353
|
+
|
|
354
|
+
The SmartLinks SDK is organised into namespaces. See `docs/API_SUMMARY.md` for the complete reference. Key namespaces:
|
|
355
|
+
|
|
356
|
+
- `appConfiguration` — Config and data storage (most apps use this)
|
|
357
|
+
- `attestation` — Proof-level user/admin data
|
|
358
|
+
- `interactions` — Event tracking and analytics
|
|
359
|
+
- `ai` — AI content generation, chat, RAG (see `docs/ai.md`)
|
|
360
|
+
- `auth` / `authKit` — Admin and end-user authentication
|
|
361
|
+
- `contact` — Customer contact management
|
|
362
|
+
- `comms` / `broadcasts` — Notifications and campaigns
|
|
363
|
+
- `asset` — File/image uploads
|
|
364
|
+
- `adminCards` — the collection's dashboard: `list`, `refresh`, `saveLayout` (see `docs/admin-cards.md`)
|
|
365
|
+
- `realtime` — SmartLinks Realtime: `onChange`, `channel`, `onMine` (see `docs/realtime.md`)
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## File Structure
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
├── index.html ← Public portal entry
|
|
373
|
+
├── admin.html ← Admin console entry
|
|
374
|
+
├── public/
|
|
375
|
+
│ ├── app.manifest.json ← Public discovery manifest
|
|
376
|
+
│ ├── app.admin.json ← Admin manifest (on-demand)
|
|
377
|
+
│ └── ai-guide.md ← AI orchestrator prose guide
|
|
378
|
+
├── src/
|
|
379
|
+
│ ├── main.tsx ← Public React entry
|
|
380
|
+
│ ├── admin-main.tsx ← Admin React entry
|
|
381
|
+
│ ├── App.tsx ← Shared providers (QueryClient, Toaster, etc.)
|
|
382
|
+
│ ├── PublicApp.tsx ← Public app shell (routes only public pages)
|
|
383
|
+
│ ├── AdminApp.tsx ← Admin app shell (routes only admin pages)
|
|
384
|
+
│ ├── components/ ← Reusable UI components
|
|
385
|
+
│ ├── containers/ ← Embeddable full-app containers
|
|
386
|
+
│ ├── executor/ ← Executor bundle (SEO, LLM content, config API)
|
|
387
|
+
│ ├── hooks/ ← React hooks (data fetching, state)
|
|
388
|
+
│ ├── pages/
|
|
389
|
+
│ │ ├── PublicPage.tsx ← Portal content (/#/)
|
|
390
|
+
│ │ ├── AdminPage.tsx ← Admin content (admin.html#/)
|
|
391
|
+
│ │ └── DevPage.tsx ← Development helper (dev only)
|
|
392
|
+
│ ├── widgets/ ← Embeddable widget components
|
|
393
|
+
│ └── utils/
|
|
394
|
+
│ ├── smartlinks/ ← SmartLinks utilities
|
|
395
|
+
│ └── theme.ts ← Theme utilities
|
|
396
|
+
├── vite.config.ts ← Multi-page build config
|
|
397
|
+
├── vite.config.widget.ts ← Widget library build config
|
|
398
|
+
├── vite.config.container.ts ← Container library build config
|
|
399
|
+
└── vite.config.executor.ts ← Executor library build config
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Anti-Patterns to Avoid
|
|
405
|
+
|
|
406
|
+
❌ **Don't implement custom auth** — Use SmartLinks auth via `SL.auth.getAccount()`
|
|
407
|
+
|
|
408
|
+
❌ **Don't use BrowserRouter** — Always use HashRouter for iframe compatibility
|
|
409
|
+
|
|
410
|
+
❌ **Don't hardcode URLs** — Use relative paths and let the platform provide context
|
|
411
|
+
|
|
412
|
+
❌ **Don't store secrets in code** — Use environment variables or platform configuration
|
|
413
|
+
|
|
414
|
+
❌ **Don't assume screen size** — Support both mobile (Portal) and desktop (Admin)
|
|
415
|
+
|
|
416
|
+
❌ **Don't expose technical IDs** — Show human-readable names to users
|
|
417
|
+
|
|
418
|
+
❌ **Don't import AdminPage in PublicApp** — Keep bundles separate for optimal size
|
|
419
|
+
|
|
420
|
+
❌ **Don't use external AI services** — Use SmartLinks AI via `SL.ai`, not OpenAI/Anthropic/Lovable Cloud AI directly
|
|
421
|
+
|
|
422
|
+
❌ **Don't forget `admin: true`** — All admin write operations require this flag
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## Quick Reference
|
|
427
|
+
|
|
428
|
+
### Initialise the API
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
import { initializeAPI } from '@/utils/smartlinks/initialization';
|
|
432
|
+
initializeAPI(); // Call once at app startup
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Get Context from URL
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
const { persistentQueryParams } = usePersistentQueryParams();
|
|
439
|
+
const { collectionId, productId, appId } = persistentQueryParams;
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Check Admin Status
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
const account = await SL.auth.getAccount();
|
|
446
|
+
const isAdmin = account?.admin === true;
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Save Configuration (Admin Only)
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
await SL.appConfiguration.setConfig({
|
|
453
|
+
collectionId, appId,
|
|
454
|
+
config: { myKey: 'myValue' },
|
|
455
|
+
admin: true // Required!
|
|
456
|
+
});
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Handle Dark Mode + Theming
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
// In App.tsx — already integrated in the template
|
|
463
|
+
useDarkMode(); // Handles ?dark=1 parameter
|
|
464
|
+
useSmartLinksTheme(); // Handles ?theme=base64 parameter
|
|
465
|
+
useDeepLinkSync(); // Syncs route changes to parent
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Deep Linking
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
const { navigateWithState, getAppState } = usePersistentQueryParams();
|
|
472
|
+
const { tab = 'general' } = getAppState();
|
|
473
|
+
navigateWithState('/', { tab: 'advanced' });
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
See `docs/deep-link-discovery.md` for full implementation details.
|