@picked/client 0.0.1-dev.1785305085063 → 0.0.1-dev.1785908062293

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/api-03c5jvVk.js +38 -0
  3. package/dist/api-CQxCVIrm.cjs +1 -0
  4. package/dist/cjs/form/index.js +1 -1
  5. package/dist/cjs/index.js +2 -2
  6. package/dist/cjs/plugins/dom-observer/index.js +1 -1
  7. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  8. package/dist/cjs/server/index.js +1 -1
  9. package/dist/docs/explanation/conditions-and-the-logic-engine.md +94 -0
  10. package/dist/docs/explanation/feature-flag-allocation.md +176 -0
  11. package/dist/docs/explanation/how-picked-works.md +124 -0
  12. package/dist/docs/explanation/how-pickedql-works.md +76 -0
  13. package/dist/docs/explanation/pages-and-flows.md +64 -0
  14. package/dist/docs/explanation/the-content-model.md +77 -0
  15. package/dist/docs/explanation/the-two-apis.md +68 -0
  16. package/dist/docs/explanation/why-server-side-rendering.md +76 -0
  17. package/dist/docs/explanation/workspaces-and-versions.md +71 -0
  18. package/dist/docs/how-to/add-a-step-field-or-action.md +43 -0
  19. package/dist/docs/{pickedql/examples.md → how-to/analytics/index.md} +53 -28
  20. package/dist/docs/how-to/archive-or-delete-a-workspace.md +46 -0
  21. package/dist/docs/how-to/authenticate-with-a-magic-link.md +40 -0
  22. package/dist/docs/how-to/authenticate-with-a-password.md +51 -0
  23. package/dist/docs/how-to/authenticate-with-an-api-key.md +51 -0
  24. package/dist/docs/how-to/authenticate-with-oauth.md +40 -0
  25. package/dist/docs/how-to/build-a-flow.md +83 -0
  26. package/dist/docs/how-to/connect-the-mcp-server.md +38 -0
  27. package/dist/docs/how-to/create-a-project.md +29 -0
  28. package/dist/docs/how-to/create-an-experience.md +42 -0
  29. package/dist/docs/how-to/create-and-revoke-an-api-key.md +37 -0
  30. package/dist/docs/how-to/debug-with-the-chrome-extension.md +57 -0
  31. package/dist/docs/how-to/define-a-page-layout.md +39 -0
  32. package/dist/docs/how-to/fill-and-publish-a-page.md +50 -0
  33. package/dist/docs/how-to/install-the-gtm-template.md +84 -0
  34. package/dist/docs/how-to/install-the-sdk.md +68 -0
  35. package/dist/docs/how-to/install-the-vite-plugin.md +56 -0
  36. package/dist/docs/how-to/invite-and-remove-members.md +34 -0
  37. package/dist/docs/how-to/preview-a-workspace.md +28 -0
  38. package/dist/docs/how-to/publish-a-workspace.md +30 -0
  39. package/dist/docs/how-to/read-a-feature-flag.md +101 -0
  40. package/dist/docs/how-to/register-a-component.md +55 -0
  41. package/dist/docs/how-to/register-an-action-handler.md +67 -0
  42. package/dist/docs/how-to/render-a-step-form.md +132 -0
  43. package/dist/docs/how-to/render-an-unpublished-preview.md +41 -0
  44. package/dist/docs/how-to/reuse-a-section.md +37 -0
  45. package/dist/docs/how-to/reuse-a-step-field-or-action.md +28 -0
  46. package/dist/docs/how-to/roll-back-a-published-version.md +26 -0
  47. package/dist/docs/how-to/run-an-ab-test.md +49 -0
  48. package/dist/docs/how-to/run-code-on-a-form-submission.md +125 -0
  49. package/dist/docs/how-to/server-render-a-page.md +81 -0
  50. package/dist/docs/how-to/set-a-content-security-policy.md +32 -0
  51. package/dist/docs/how-to/set-up-mfa.md +69 -0
  52. package/dist/docs/how-to/upload-and-use-an-asset.mdx +73 -0
  53. package/dist/docs/how-to/validate-a-field.md +52 -0
  54. package/dist/docs/how-to/write-a-condition.md +45 -0
  55. package/dist/docs/how-to/write-a-predicate.md +60 -0
  56. package/dist/docs/index.md +41 -59
  57. package/dist/docs/reference/dashboard/actions.mdx +53 -0
  58. package/dist/docs/reference/dashboard/api-keys.mdx +37 -0
  59. package/dist/docs/reference/dashboard/conditions.mdx +42 -0
  60. package/dist/docs/reference/dashboard/content/asset-library.mdx +63 -0
  61. package/dist/docs/reference/dashboard/content/content-entries.mdx +44 -0
  62. package/dist/docs/reference/dashboard/content/layouts.mdx +62 -0
  63. package/dist/docs/reference/dashboard/content/pages.mdx +35 -0
  64. package/dist/docs/reference/dashboard/content/sections.mdx +28 -0
  65. package/dist/docs/reference/dashboard/experiences.mdx +51 -0
  66. package/dist/docs/reference/dashboard/features.mdx +114 -0
  67. package/dist/docs/reference/dashboard/fields.mdx +100 -0
  68. package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +58 -0
  69. package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +57 -0
  70. package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +72 -0
  71. package/dist/docs/reference/dashboard/flow-builder/nodes.md +63 -0
  72. package/dist/docs/reference/dashboard/projects.mdx +44 -0
  73. package/dist/docs/reference/dashboard/reports.mdx +43 -0
  74. package/dist/docs/reference/dashboard/steps.mdx +37 -0
  75. package/dist/docs/reference/dashboard/team-management.md +29 -0
  76. package/dist/docs/reference/dashboard/workspace-versioning.mdx +30 -0
  77. package/dist/docs/reference/dashboard/workspaces.mdx +76 -0
  78. package/dist/docs/{delivery-api → reference/delivery-api}/experience-content.md +17 -5
  79. package/dist/docs/reference/delivery-api/index.md +45 -0
  80. package/dist/docs/reference/delivery-api/preview-caching-crawling.md +79 -0
  81. package/dist/docs/{delivery-api → reference/delivery-api}/project-config.md +15 -6
  82. package/dist/docs/reference/glossary.md +173 -0
  83. package/dist/docs/reference/management-api/authentication.md +74 -0
  84. package/dist/docs/{api → reference/management-api}/authorization-and-scopes.md +70 -47
  85. package/dist/docs/reference/management-api/error-handling.md +233 -0
  86. package/dist/docs/{api → reference/management-api}/pagination.md +36 -20
  87. package/dist/docs/reference/pickedql/data-sources.md +174 -0
  88. package/dist/docs/reference/pickedql/dimensions.md +87 -0
  89. package/dist/docs/{pickedql → reference/pickedql}/filtering.md +17 -6
  90. package/dist/docs/reference/pickedql/index.md +18 -0
  91. package/dist/docs/reference/pickedql/schema.md +172 -0
  92. package/dist/docs/reference/pickedql/virtual-functions.md +237 -0
  93. package/dist/docs/reference/sdk/actions.md +30 -0
  94. package/dist/docs/{sdk → reference/sdk}/conditions.md +15 -5
  95. package/dist/docs/reference/sdk/content-security-policy.md +21 -0
  96. package/dist/docs/reference/sdk/experiences.md +51 -0
  97. package/dist/docs/reference/sdk/features.md +233 -0
  98. package/dist/docs/reference/sdk/fields.md +209 -0
  99. package/dist/docs/reference/sdk/index.md +68 -0
  100. package/dist/docs/{sdk → reference/sdk}/plugins/create-experience.md +25 -34
  101. package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +74 -0
  102. package/dist/docs/reference/sdk/plugins/index.md +29 -0
  103. package/dist/docs/{sdk → reference/sdk}/plugins/window-object.md +6 -0
  104. package/dist/docs/reference/sdk/predicates.md +43 -0
  105. package/dist/docs/reference/sdk/ssr/index.md +33 -0
  106. package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +103 -0
  107. package/dist/docs/reference/sdk/ssr/serialize.md +77 -0
  108. package/dist/docs/reference/sdk/ssr/slots-and-placements.md +59 -0
  109. package/dist/docs/reference/sdk/steps.md +87 -0
  110. package/dist/docs/reference/tools/chrome-extension.md +16 -0
  111. package/dist/docs/reference/tools/image-optimisation-service.md +104 -0
  112. package/dist/docs/reference/tools/mcp.md +88 -0
  113. package/dist/docs/reference/tools/vite-plugin.md +88 -0
  114. package/dist/docs/tutorials/first-api-call.md +228 -0
  115. package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +143 -0
  116. package/dist/docs/tutorials/first-experience.mdx +255 -0
  117. package/dist/docs/tutorials/first-server-rendered-page.mdx +186 -0
  118. package/dist/{dom-BwmTHeT7.js → dom-BqcToNL0.js} +1 -3
  119. package/dist/{dom-CDrHc_j9.cjs → dom-DlLH3FxV.cjs} +1 -1
  120. package/dist/esm/form/index.js +2 -4
  121. package/dist/esm/index.js +225 -186
  122. package/dist/esm/plugins/dom-observer/index.js +1 -1
  123. package/dist/esm/plugins/dynamic-experiences/index.js +3 -3
  124. package/dist/esm/preview/index.js +1 -1
  125. package/dist/esm/server/index.js +33 -31
  126. package/dist/{experience-instance-DOJShRk5.js → experience-instance-DGk11d8a.js} +3 -3
  127. package/dist/experience-instance-Dej3P1sE.cjs +1 -0
  128. package/dist/plugin-CHOVsx7Z.js +287 -0
  129. package/dist/plugin-DsaGXQHx.cjs +1 -0
  130. package/dist/{preview-channel-DW9J8t4B.js → preview-channel-CSr96XAo.js} +1 -1
  131. package/dist/{protocol-DSqOlW2r.js → protocol-C5KkkiZc.js} +1 -1
  132. package/dist/types/client.d.ts +7 -6
  133. package/dist/types/data-source/api.d.ts +60 -0
  134. package/dist/types/data-source/api.d.ts.map +1 -0
  135. package/dist/types/data-source/provider.d.ts +97 -0
  136. package/dist/types/data-source/provider.d.ts.map +1 -0
  137. package/dist/types/entities/action/action.d.ts +5 -4
  138. package/dist/types/entities/action/action.d.ts.map +1 -1
  139. package/dist/types/entities/component/component.d.ts +6 -5
  140. package/dist/types/entities/component/component.d.ts.map +1 -1
  141. package/dist/types/entities/condition/condition.d.ts +5 -5
  142. package/dist/types/entities/content/content.d.ts +4 -3
  143. package/dist/types/entities/experience/experience.d.ts +11 -10
  144. package/dist/types/entities/experience/experience.d.ts.map +1 -1
  145. package/dist/types/entities/experience-instance/experience-instance.d.ts +10 -9
  146. package/dist/types/entities/feature/feature.d.ts +19 -2
  147. package/dist/types/entities/feature/feature.d.ts.map +1 -1
  148. package/dist/types/entities/field/field.d.ts +7 -6
  149. package/dist/types/entities/framework/framework.d.ts +7 -6
  150. package/dist/types/entities/framework/framework.d.ts.map +1 -1
  151. package/dist/types/entities/history/history.d.ts +6 -6
  152. package/dist/types/entities/plugin/plugin.d.ts +3 -2
  153. package/dist/types/entities/plugin/plugin.d.ts.map +1 -1
  154. package/dist/types/entities/predicate/predicate.d.ts +4 -3
  155. package/dist/types/entities/predicate/predicate.d.ts.map +1 -1
  156. package/dist/types/entities/response/response-validation.d.ts +3 -2
  157. package/dist/types/entities/response/response.d.ts +12 -11
  158. package/dist/types/entities/session/session.d.ts +2 -1
  159. package/dist/types/entities/step/step.d.ts +6 -5
  160. package/dist/types/exports.d.ts +2 -1
  161. package/dist/types/exports.d.ts.map +1 -1
  162. package/dist/types/form/build-responses.d.ts +2 -1
  163. package/dist/types/form/create-field-evaluator.d.ts +4 -3
  164. package/dist/types/form/create-field-validation.d.ts +5 -4
  165. package/dist/types/form/create-form.d.ts +7 -6
  166. package/dist/types/form/create-submit-pipeline.d.ts +7 -6
  167. package/dist/types/form/get-step-fields.d.ts +3 -2
  168. package/dist/types/lifecycle/condition-selection.d.ts +14 -4
  169. package/dist/types/lifecycle/lifecycle.d.ts +4 -3
  170. package/dist/types/lifecycle/rules-logic.d.ts +4 -3
  171. package/dist/types/lifecycle/state-snapshot.d.ts +4 -3
  172. package/dist/types/picked.d.ts +79 -62
  173. package/dist/types/picked.d.ts.map +1 -1
  174. package/dist/types/ping.d.ts +1 -1
  175. package/dist/types/ping.d.ts.map +1 -1
  176. package/dist/types/plugins/create-experience/create-experience.d.ts +9 -8
  177. package/dist/types/plugins/create-experience/create-experience.d.ts.map +1 -1
  178. package/dist/types/plugins/create-experience/plugin.d.ts +3 -2
  179. package/dist/types/plugins/create-experience/plugin.d.ts.map +1 -1
  180. package/dist/types/plugins/create-experience/serialization.d.ts.map +1 -1
  181. package/dist/types/plugins/dom-observer/plugin.d.ts +1 -1
  182. package/dist/types/plugins/dynamic-experiences/hash.d.ts +40 -5
  183. package/dist/types/plugins/dynamic-experiences/hash.d.ts.map +1 -1
  184. package/dist/types/plugins/dynamic-experiences/index.d.ts +2 -0
  185. package/dist/types/plugins/dynamic-experiences/index.d.ts.map +1 -1
  186. package/dist/types/plugins/dynamic-experiences/plugin.d.ts +4 -36
  187. package/dist/types/plugins/dynamic-experiences/plugin.d.ts.map +1 -1
  188. package/dist/types/plugins/dynamic-experiences/types.d.ts +42 -11
  189. package/dist/types/plugins/dynamic-experiences/types.d.ts.map +1 -1
  190. package/dist/types/plugins/experience-browser-storage/plugin.d.ts +1 -1
  191. package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
  192. package/dist/types/plugins/history-browser-storage/plugin.d.ts +1 -1
  193. package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
  194. package/dist/types/plugins/responses-browser-storage/plugin.d.ts +1 -1
  195. package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
  196. package/dist/types/plugins/responses-indexeddb/plugin.d.ts +1 -1
  197. package/dist/types/plugins/single-page-app/plugin.d.ts +1 -1
  198. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  199. package/dist/types/plugins/web-components/plugin.d.ts +2 -1
  200. package/dist/types/plugins/window-object/plugin.d.ts +2 -2
  201. package/dist/types/preview-channel.d.ts +5 -1
  202. package/dist/types/preview-receiver/index.d.ts +18 -1
  203. package/dist/types/preview-receiver/protocol.d.ts +10 -1
  204. package/dist/types/server/index.d.ts +3 -3
  205. package/dist/types/server/serialize.d.ts +8 -2
  206. package/dist/types/server/serialize.d.ts.map +1 -1
  207. package/dist/types/utils/dom.d.ts +2 -1
  208. package/dist/types/utils/events.d.ts +6 -6
  209. package/dist/types/utils/events.d.ts.map +1 -1
  210. package/dist/types/utils/global-obj.d.ts +1 -1
  211. package/dist/types/utils/global-obj.d.ts.map +1 -1
  212. package/dist/types/utils/id.d.ts.map +1 -1
  213. package/dist/types/utils/logger.d.ts +2 -1
  214. package/dist/types/utils/logger.d.ts.map +1 -1
  215. package/dist/types/utils/node-tree/get-next-node-from-action.d.ts +2 -1
  216. package/dist/types/utils/node-tree/get-next-node-from-condition.d.ts +2 -1
  217. package/dist/types/utils/node-tree/get-next-node.d.ts +1 -1
  218. package/dist/types/utils/node-tree/get-next-node.d.ts.map +1 -1
  219. package/dist/types/utils/node-tree/get-origin-node.d.ts +1 -1
  220. package/dist/types/utils/node-tree/get-origin-node.d.ts.map +1 -1
  221. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts +1 -1
  222. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts.map +1 -1
  223. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts +1 -1
  224. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts.map +1 -1
  225. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts +1 -1
  226. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts.map +1 -1
  227. package/dist/types/utils/nodes.d.ts +1 -1
  228. package/dist/types/utils/picked-config.d.ts +2 -1
  229. package/dist/types/utils/rehydrate-scripts.d.ts +6 -0
  230. package/dist/types/utils/rehydrate-scripts.d.ts.map +1 -1
  231. package/dist/types/utils/rules-logic.d.ts +6 -2
  232. package/dist/types/utils/storage.d.ts +1 -1
  233. package/dist/types/utils/storage.d.ts.map +1 -1
  234. package/package.json +22 -23
  235. package/dist/api-CPL40b7A.js +0 -40
  236. package/dist/api-Dz5rgRgQ.cjs +0 -1
  237. package/dist/docs/actions.mdx +0 -78
  238. package/dist/docs/api/authentication.md +0 -376
  239. package/dist/docs/api/error-handling.md +0 -211
  240. package/dist/docs/api/index.md +0 -197
  241. package/dist/docs/api-keys.mdx +0 -40
  242. package/dist/docs/chrome-extension.md +0 -51
  243. package/dist/docs/conditions.mdx +0 -59
  244. package/dist/docs/content/asset-library.mdx +0 -93
  245. package/dist/docs/content/content-entries.mdx +0 -30
  246. package/dist/docs/content/layouts.mdx +0 -70
  247. package/dist/docs/content/pages.mdx +0 -67
  248. package/dist/docs/content/sections.mdx +0 -33
  249. package/dist/docs/delivery-api/index.md +0 -46
  250. package/dist/docs/delivery-api/preview-caching-crawling.md +0 -59
  251. package/dist/docs/experiences.mdx +0 -42
  252. package/dist/docs/features.mdx +0 -58
  253. package/dist/docs/fields.mdx +0 -79
  254. package/dist/docs/flow-builder/building-flows.md +0 -61
  255. package/dist/docs/flow-builder/condition-builder.md +0 -54
  256. package/dist/docs/flow-builder/keyboard-shortcuts.md +0 -66
  257. package/dist/docs/flow-builder/nodes.md +0 -43
  258. package/dist/docs/flow-builder/overview.mdx +0 -50
  259. package/dist/docs/gtm-template.md +0 -69
  260. package/dist/docs/guides/build-a-personalized-page.mdx +0 -143
  261. package/dist/docs/image-optimisation-service.md +0 -80
  262. package/dist/docs/mcp.md +0 -120
  263. package/dist/docs/pickedql/data-sources.md +0 -145
  264. package/dist/docs/pickedql/dimensions.md +0 -65
  265. package/dist/docs/pickedql/index.md +0 -36
  266. package/dist/docs/pickedql/schema.md +0 -156
  267. package/dist/docs/pickedql/virtual-functions.md +0 -204
  268. package/dist/docs/projects.mdx +0 -37
  269. package/dist/docs/reports.mdx +0 -18
  270. package/dist/docs/sdk/actions.md +0 -66
  271. package/dist/docs/sdk/content-security-policy.md +0 -32
  272. package/dist/docs/sdk/experiences.md +0 -46
  273. package/dist/docs/sdk/features.md +0 -212
  274. package/dist/docs/sdk/fields.md +0 -263
  275. package/dist/docs/sdk/index.md +0 -83
  276. package/dist/docs/sdk/plugins/dynamic-experiences.md +0 -58
  277. package/dist/docs/sdk/plugins/index.md +0 -9
  278. package/dist/docs/sdk/predicates.md +0 -112
  279. package/dist/docs/sdk/ssr/index.md +0 -62
  280. package/dist/docs/sdk/ssr/rendering-and-hydration.md +0 -141
  281. package/dist/docs/sdk/ssr/serialize.md +0 -86
  282. package/dist/docs/sdk/ssr/slots-and-placements.md +0 -35
  283. package/dist/docs/sdk/steps.md +0 -434
  284. package/dist/docs/steps.mdx +0 -44
  285. package/dist/docs/team-management.md +0 -40
  286. package/dist/docs/vite-plugin.md +0 -82
  287. package/dist/docs/workspace-versioning.mdx +0 -28
  288. package/dist/docs/workspaces.mdx +0 -102
  289. package/dist/experience-instance-DurC3pE-.cjs +0 -1
  290. package/dist/plugin-CFXwbXeM.js +0 -247
  291. package/dist/plugin-m4qekgtA.cjs +0 -1
@@ -1,112 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Predicates
6
-
7
- Predicates enable reusable condition logic based on current application state. Each predicate is a pure function that receives a state snapshot containing responses, fields, browser context, and optional arguments.
8
-
9
- ## Defining Predicates
10
-
11
- Define predicates when creating the Picked client by passing a `predicates` object. Each predicate requires a unique identifier and a function that receives a state snapshot:
12
-
13
- ```ts
14
- import { createClient } from '@picked/client'
15
-
16
- const client = createClient({
17
- projectId: 'your-project-id',
18
- predicates: {
19
- 'is-example-page': ({ location }) => {
20
- return location?.pathname === '/example'
21
- },
22
- 'get-account-tier': async () => {
23
- const data = await fetch('/api/get-account-tier').then((r) => r.json())
24
- return data.result // returns "trial"
25
- },
26
- },
27
- })
28
- ```
29
-
30
- ## How Predicates Work
31
-
32
- When a predicate is registered and used in conditions, the SDK follows this execution flow:
33
-
34
- 1. **Registration**: Predicates are registered to the Picked client during initialization
35
- 2. **State Snapshot Creation**: When invoked, predicates receive a frozen state snapshot containing current responses, fields, and browser context
36
- 3. **Condition Evaluation**: Experience conditions invoke predicates with a fresh snapshot whenever called
37
- 4. **Return Flexibility**: Predicates can return boolean, string, string array, undefined, or promises that resolve to these types
38
-
39
- ## Using Predicates in Conditions
40
-
41
- Predicates are most commonly used within condition logic via the `invoke` operator:
42
-
43
- ```ts
44
- const myExperience = createExperience({
45
- // ... other config
46
- condition: {
47
- and: [
48
- {
49
- '==': [
50
- {
51
- invoke: {
52
- var: 'predicates.is-example-page', // Reference predicate that calls user endpoint
53
- },
54
- },
55
- true, // Check if return value is true
56
- ],
57
- },
58
- {
59
- '==': [
60
- {
61
- invoke: {
62
- var: 'predicates.account-tier',
63
- },
64
- },
65
- '/trial', // If string matches, evaluate to true
66
- ],
67
- },
68
- ],
69
- },
70
- })
71
- ```
72
-
73
- :::tip
74
- Predicates can also be used in `validation` logic
75
- :::
76
-
77
- ## Using the State Snapshot
78
-
79
- Each predicate receives a `StateSnapshot` object with the following properties:
80
-
81
- ```ts
82
- interface StateSnapshot {
83
- client: Picked // The Picked client instance
84
- responses?: Array<{
85
- // All user responses
86
- fieldId: string
87
- value: FieldValue | undefined
88
- }>
89
- args?: unknown[]
90
- fields?: Field[] // All registered fields
91
- location?: Location // Browser location (URL, pathname, search, etc.)
92
- document?: Document // Browser document object
93
- sessionStorage?: Storage // Browser sessionStorage API
94
- localStorage?: Storage // Browser localStorage API
95
- }
96
- ```
97
-
98
- :::warning
99
- In server-side rendering or non-browser environments, `location`, `document`, `sessionStorage`,
100
- and `localStorage` will be `undefined`.
101
- :::
102
-
103
- ## Best Practices
104
-
105
- - **Keep predicates pure**: Predicates should be deterministic and side-effect free. Given the same snapshot, they should always return the same result
106
- - **Handle missing data gracefully**: Always check if responses or fields exist before accessing their values. Return `undefined` when data is unavailable rather than throwing errors
107
- - **Avoid heavy computations**: Predicates may be invoked frequently. Keep logic lightweight and fast
108
- - **Use async sparingly**: While async predicates are supported, they can delay experience rendering. Prefer synchronous logic when possible
109
- - **Return consistent types**: Don't mix return types (e.g., sometimes boolean, sometimes string) for the same predicate
110
- - **Use meaningful names**: Predicate IDs should clearly describe what they evaluate (e.g., `is-premium-user`, `has-items-in-cart`)
111
- - **Consider caching expensive operations**: If a predicate needs to perform expensive operations, consider caching the result in `localStorage` or `sessionStorage` within the predicate logic
112
- - **Don't mutate the snapshot**: The state snapshot is frozen. Any attempt to modify it will throw an error in strict mode
@@ -1,62 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Server-Side Rendering
6
-
7
- Render Picked Pages on your server for SEO, then hydrate them on the client. This page shows the end-to-end shape; the following pages cover each piece.
8
-
9
- ## Why server-side rendering
10
-
11
- Pages are SEO-critical, so their content must be in the HTML your server returns. Crawlers and social unfurls read that HTML directly and do not wait for client-side JavaScript. Rendering a Page on the server puts its content in the initial response, then the client takes over.
12
-
13
- ## The flow
14
-
15
- ```
16
- projectConfig (Delivery API)
17
- -> serialize(client, params) on the server -> PickedSnapshot
18
- -> embed snapshot in HTML
19
- -> client seeds from snapshot -> renders the same markup -> hydrates
20
- ```
21
-
22
- 1. Fetch your published `projectConfig` from the [Delivery API](/delivery-api).
23
- 2. Call `serialize()` on the server. It evaluates which experiences match the URL, fetches their content, and returns a plain-JSON `PickedSnapshot`. See [Server Snapshot](/sdk/ssr/serialize).
24
- 3. Embed the snapshot in your HTML payload.
25
- 4. On the client, seed a Picked client from the snapshot so the first paint matches the server markup, then hydrate. See [Rendering & Hydration](/sdk/ssr/rendering-and-hydration).
26
-
27
- Because the snapshot carries the exact config the server selected with and the memoized condition results, the client's first render reuses the server's decisions instead of re-evaluating them.
28
-
29
- ## React vs Svelte at a glance
30
-
31
- :::code-group
32
-
33
- ```tsx [React]
34
- import { PickedProvider, ExperienceSlot } from '@picked/react'
35
-
36
- <PickedProvider options={options} snapshot={snapshot}>
37
- <ExperienceSlot name="page" />
38
- </PickedProvider>
39
- ```
40
-
41
- ```svelte [Svelte]
42
- <script lang="ts">
43
- import { ExperienceSlot, setPickedContext } from '@picked/svelte'
44
-
45
- setPickedContext({ options, snapshot })
46
- </script>
47
-
48
- <ExperienceSlot name="page" />
49
- ```
50
-
51
- :::
52
-
53
- ## The server entry point
54
-
55
- The server helpers live in a dedicated entry so browser bundles never pull them in:
56
-
57
- ```ts
58
- import { serialize, registerProjectConfig } from '@picked/client/server'
59
- import type { PickedSnapshot } from '@picked/client/server'
60
- ```
61
-
62
- Continue to [Server Snapshot](/sdk/ssr/serialize) for the `serialize()` reference, [Rendering & Hydration](/sdk/ssr/rendering-and-hydration) for wiring React and Svelte, and [Slots & Placements](/sdk/ssr/slots-and-placements) for how a slot selects experiences. New to the SDK? Start with [Installation](/sdk).
@@ -1,141 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Rendering & Hydration
6
-
7
- Seed a Picked client from the server snapshot, render your slots, and hydrate. React and Svelte below.
8
-
9
- ## React: PickedProvider
10
-
11
- `PickedProvider` supplies a client to descendant components. Its props are a union of two construction modes:
12
-
13
- | Props | Mode | Description |
14
- | --- | --- | --- |
15
- | `{ options, snapshot? }` | Create | The provider calls `createClient(options)` and hydrates it from the snapshot. |
16
- | `{ client, snapshot? }` | Adopt | The provider uses an existing client, such as an app-wide global, and optionally seeds it from the snapshot. |
17
-
18
- The provider seeds synchronously, so the server render and the client's first paint produce the same markup. In the browser it calls `client.start()` from an effect; `start()` is idempotent, so an already-started client is left untouched.
19
-
20
- ```tsx
21
- import { PickedProvider, ExperienceSlot } from '@picked/react'
22
-
23
- <PickedProvider options={options} snapshot={snapshot}>
24
- <ExperienceSlot name="page" />
25
- </PickedProvider>
26
- ```
27
-
28
- ## Svelte: setPickedContext
29
-
30
- `setPickedContext` is the Svelte-idiomatic equivalent. Call it once at the top of a component's `<script>`. It takes the same two modes, `{ options, snapshot? }` or `{ client, snapshot? }`, and returns the client.
31
-
32
- ```svelte
33
- <script lang="ts">
34
- import { ExperienceSlot, setPickedContext } from '@picked/svelte'
35
-
36
- setPickedContext({ options, snapshot })
37
- </script>
38
-
39
- <ExperienceSlot name="page" />
40
- ```
41
-
42
- ## Placing the slot
43
-
44
- Drop `<ExperienceSlot name="page" />` where the Page should render. The slot renders every experience that targets it and whose condition is active. See [Slots & Placements](/sdk/ssr/slots-and-placements) for how a slot selects and orders experiences.
45
-
46
- ## Rendering the page component
47
-
48
- The SDK does not map content to components. You own the component a Page renders and register it under the name the Page uses, which is the same name the dashboard Page Layout maps to. The component reads the resolved entry data through the content hook: `useStepContent()` in React and `getStepContent()` in Svelte.
49
-
50
- :::code-group
51
-
52
- ```tsx [React]
53
- import { useStepContent } from '@picked/react/hooks'
54
-
55
- export function CMSPage() {
56
- const content = useStepContent()
57
- if (!content) {
58
- return <p>Loading page content…</p>
59
- }
60
-
61
- const title = typeof content.title === 'string' ? content.title : ''
62
- return (
63
- <article>
64
- <h1>{title}</h1>
65
- </article>
66
- )
67
- }
68
- ```
69
-
70
- ```svelte [Svelte]
71
- <script lang="ts">
72
- import { getStepContent } from '@picked/svelte/hooks'
73
-
74
- const content = getStepContent()
75
- </script>
76
-
77
- {#if $content}
78
- <article>
79
- <h1>{typeof $content.title === 'string' ? $content.title : ''}</h1>
80
- </article>
81
- {:else}
82
- <p>Loading page content…</p>
83
- {/if}
84
- ```
85
-
86
- :::
87
-
88
- `useStepContent()` returns the entry's `data` object directly, or `null` while no content is registered. `getStepContent()` returns a store you read with `$content`.
89
-
90
- ## Full example
91
-
92
- This is the verified page-slot wiring. The page client fetches the project config and renders whichever Page experience targets `.picked-slot-page` and matches the current URL.
93
-
94
- :::code-group
95
-
96
- ```tsx [React]
97
- import type { CreateClientOptions } from '@picked/client'
98
- import type { PickedSnapshot } from '@picked/client/server'
99
- import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
100
- import { adaptReactComponent, ExperienceSlot, PickedProvider } from '@picked/react'
101
- import { reactFrameworkPlugin } from '@picked/react/plugins/framework'
102
- import { CMSPage } from './CMSPage'
103
-
104
- const options = {
105
- projectId: 'sdk-cvly-x',
106
- components: { CMSPage: adaptReactComponent(CMSPage) },
107
- plugins: [reactFrameworkPlugin({ components: {} }), dynamicExperiencesPlugin()],
108
- } satisfies CreateClientOptions
109
-
110
- export function PageSlot({ snapshot }: { snapshot?: PickedSnapshot }) {
111
- return (
112
- <PickedProvider options={options} snapshot={snapshot}>
113
- <ExperienceSlot name="page" />
114
- </PickedProvider>
115
- )
116
- }
117
- ```
118
-
119
- ```svelte [Svelte]
120
- <script lang="ts">
121
- import type { CreateClientOptions } from '@picked/client'
122
- import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
123
- import { adaptSvelteComponent, ExperienceSlot, setPickedContext } from '@picked/svelte'
124
- import { svelteFrameworkPlugin } from '@picked/svelte/plugins/framework'
125
- import CMSPage from './CMSPage.svelte'
126
-
127
- const options = {
128
- projectId: 'sdk-cvly-x',
129
- components: { CMSPage: adaptSvelteComponent(CMSPage) },
130
- plugins: [svelteFrameworkPlugin({ components: {} }), dynamicExperiencesPlugin()],
131
- } satisfies CreateClientOptions
132
-
133
- setPickedContext({ options })
134
- </script>
135
-
136
- <ExperienceSlot name="page" />
137
- ```
138
-
139
- :::
140
-
141
- For the end-to-end version with the server snapshot, see [Build a Personalized Page](/guides/build-a-personalized-page). For the snapshot reference, see [Server Snapshot](/sdk/ssr/serialize). For how experiences register, see [SDK Experiences](/sdk/experiences).
@@ -1,86 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Server Snapshot
6
-
7
- `serialize()` evaluates which experiences match a URL and fetches their content on the server, returning a plain-JSON snapshot you pass to the client.
8
-
9
- ## serialize(client, params)
10
-
11
- ```ts
12
- import { createClient } from '@picked/client'
13
- import { serialize } from '@picked/client/server'
14
-
15
- const client = createClient(options)
16
-
17
- const snapshot = await serialize(client, {
18
- projectConfig,
19
- attributes: { location: { pathname: '/promo' } },
20
- })
21
- ```
22
-
23
- `serialize()` registers the project config on the client synchronously, evaluates each experience's condition against `attributes.location`, fetches content for the experiences whose steps reference layout content, dedupes the content blobs by id, and returns a `PickedSnapshot`. It expects a per-request client; concurrent calls on a single client are not supported.
24
-
25
- ```ts
26
- serialize(client: Picked, params: SerializeParams): Promise<PickedSnapshot>
27
- ```
28
-
29
- ## Parameters
30
-
31
- | Parameter | Type | Default | Description |
32
- | --- | --- | --- | --- |
33
- | `projectConfig` | `ProjectConfig` | required | The published or preview config to register and select against. |
34
- | `attributes.location` | `Partial<SerializeLocation>` | none | URL fields injected into the selection context, such as `pathname`. |
35
- | `getContent` | `SerializeGetContent` | runtime API | A custom content fetcher used in place of the runtime API. |
36
- | `previewToken` | `string` | none | Forwarded to the content fetch so preview content resolves during preview SSR. |
37
- | `timeoutMs` | `number` | `10000` | Per-content-fetch timeout. On timeout the blob is skipped and the render proceeds. |
38
-
39
- `SerializeLocation` carries the plain URL fields `href`, `pathname`, `search`, `hostname`, `origin`, `protocol`, `port`, `host`, and `hash`. Pass only the ones your conditions read.
40
-
41
- ## The snapshot
42
-
43
- ```ts
44
- interface PickedSnapshot {
45
- versionId: string | null
46
- projectConfig: ProjectConfig
47
- content: ContentBlob[]
48
- conditionResults: Record<string, boolean>
49
- }
50
- ```
51
-
52
- | Field | Description |
53
- | --- | --- |
54
- | `versionId` | The project version the snapshot was selected against, or `null` when unknown (for example on preview). |
55
- | `projectConfig` | The config the server selected with. It travels so the client renders against the exact same config. |
56
- | `content` | The deduped content blobs for the selected experiences. |
57
- | `conditionResults` | The memoized condition results, keyed by rule hash, so the client reuses the server's selection. |
58
-
59
- The snapshot is plain JSON. Serialize it into your HTML response with `JSON.stringify` and read it back on the client.
60
-
61
- ## Passing the snapshot to the client
62
-
63
- Embed the snapshot in your HTML payload, then hand it to the provider (React) or context (Svelte):
64
-
65
- ```ts
66
- const html = `
67
- <div id="root">${appHtml}</div>
68
- <script>window.__PICKED__ = ${JSON.stringify(snapshot)}</script>
69
- `
70
- ```
71
-
72
- On the client, read `window.__PICKED__` and pass it as the `snapshot` prop. See [Rendering & Hydration](/sdk/ssr/rendering-and-hydration).
73
-
74
- ## Preview rendering
75
-
76
- Pass `previewToken` so unpublished content resolves during preview SSR. The server has no access to the request's query string, so the token cannot be recovered any other way:
77
-
78
- ```ts
79
- const snapshot = await serialize(client, {
80
- projectConfig,
81
- attributes: { location: { pathname: '/promo' } },
82
- previewToken,
83
- })
84
- ```
85
-
86
- Use the same token when you fetch `projectConfig` from the [Delivery API](/delivery-api), so the config and the content come from the same preview surface.
@@ -1,35 +0,0 @@
1
- ---
2
- layout: docs
3
- ---
4
-
5
- # Slots & Placements
6
-
7
- A slot is a named mount point. `<ExperienceSlot name="page" />` renders every experience that targets that slot and whose condition matches.
8
-
9
- ## What a slot is
10
-
11
- A slot's `name` maps to the `.picked-slot-<name>` selector. `<ExperienceSlot name="page" />` renders every experience whose target selector is `.picked-slot-page` and whose condition is active. The slot reads each experience's active state from the seeded snapshot, so it renders synchronously during server-side rendering and the hydration first paint.
12
-
13
- ```tsx
14
- <ExperienceSlot name="page" />
15
- ```
16
-
17
- ## Targeting an experience to a slot
18
-
19
- Set the experience's target selector to `.picked-slot-<name>`. An experience targeting `.picked-slot-page` renders into `<ExperienceSlot name="page" />`. The slot name and the selector suffix must match.
20
-
21
- ## Placement order
22
-
23
- When several experiences target the same slot, they render in placement precedence:
24
-
25
- ```
26
- replace -> before -> prepend -> append -> after
27
- ```
28
-
29
- `replace` wins. If an active experience uses the `replace` placement, it renders alone and replaces every other match in the slot. Otherwise every active experience renders, in placement order.
30
-
31
- ## Multiple experiences in one slot
32
-
33
- The slot collects each experience that targets its selector, drops any whose condition is not active, and sorts the rest by placement. If a `replace` experience is among the active ones, only that experience renders. With no active `replace`, the slot renders all active experiences in `before, prepend, append, after` order.
34
-
35
- This lets one Page take over a slot with `replace`, while other slots can stack several experiences by using the non-`replace` placements. Conditions decide which experiences are active; see [Conditions](/conditions).