@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.
- package/dist/.tsbuildinfo +1 -0
- package/dist/api-03c5jvVk.js +38 -0
- package/dist/api-CQxCVIrm.cjs +1 -0
- package/dist/cjs/form/index.js +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/plugins/dom-observer/index.js +1 -1
- package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
- package/dist/cjs/server/index.js +1 -1
- package/dist/docs/explanation/conditions-and-the-logic-engine.md +94 -0
- package/dist/docs/explanation/feature-flag-allocation.md +176 -0
- package/dist/docs/explanation/how-picked-works.md +124 -0
- package/dist/docs/explanation/how-pickedql-works.md +76 -0
- package/dist/docs/explanation/pages-and-flows.md +64 -0
- package/dist/docs/explanation/the-content-model.md +77 -0
- package/dist/docs/explanation/the-two-apis.md +68 -0
- package/dist/docs/explanation/why-server-side-rendering.md +76 -0
- package/dist/docs/explanation/workspaces-and-versions.md +71 -0
- package/dist/docs/how-to/add-a-step-field-or-action.md +43 -0
- package/dist/docs/{pickedql/examples.md → how-to/analytics/index.md} +53 -28
- package/dist/docs/how-to/archive-or-delete-a-workspace.md +46 -0
- package/dist/docs/how-to/authenticate-with-a-magic-link.md +40 -0
- package/dist/docs/how-to/authenticate-with-a-password.md +51 -0
- package/dist/docs/how-to/authenticate-with-an-api-key.md +51 -0
- package/dist/docs/how-to/authenticate-with-oauth.md +40 -0
- package/dist/docs/how-to/build-a-flow.md +83 -0
- package/dist/docs/how-to/connect-the-mcp-server.md +38 -0
- package/dist/docs/how-to/create-a-project.md +29 -0
- package/dist/docs/how-to/create-an-experience.md +42 -0
- package/dist/docs/how-to/create-and-revoke-an-api-key.md +37 -0
- package/dist/docs/how-to/debug-with-the-chrome-extension.md +57 -0
- package/dist/docs/how-to/define-a-page-layout.md +39 -0
- package/dist/docs/how-to/fill-and-publish-a-page.md +50 -0
- package/dist/docs/how-to/install-the-gtm-template.md +84 -0
- package/dist/docs/how-to/install-the-sdk.md +68 -0
- package/dist/docs/how-to/install-the-vite-plugin.md +56 -0
- package/dist/docs/how-to/invite-and-remove-members.md +34 -0
- package/dist/docs/how-to/preview-a-workspace.md +28 -0
- package/dist/docs/how-to/publish-a-workspace.md +30 -0
- package/dist/docs/how-to/read-a-feature-flag.md +101 -0
- package/dist/docs/how-to/register-a-component.md +55 -0
- package/dist/docs/how-to/register-an-action-handler.md +67 -0
- package/dist/docs/how-to/render-a-step-form.md +132 -0
- package/dist/docs/how-to/render-an-unpublished-preview.md +41 -0
- package/dist/docs/how-to/reuse-a-section.md +37 -0
- package/dist/docs/how-to/reuse-a-step-field-or-action.md +28 -0
- package/dist/docs/how-to/roll-back-a-published-version.md +26 -0
- package/dist/docs/how-to/run-an-ab-test.md +49 -0
- package/dist/docs/how-to/run-code-on-a-form-submission.md +125 -0
- package/dist/docs/how-to/server-render-a-page.md +81 -0
- package/dist/docs/how-to/set-a-content-security-policy.md +32 -0
- package/dist/docs/how-to/set-up-mfa.md +69 -0
- package/dist/docs/how-to/upload-and-use-an-asset.mdx +73 -0
- package/dist/docs/how-to/validate-a-field.md +52 -0
- package/dist/docs/how-to/write-a-condition.md +45 -0
- package/dist/docs/how-to/write-a-predicate.md +60 -0
- package/dist/docs/index.md +41 -59
- package/dist/docs/reference/dashboard/actions.mdx +53 -0
- package/dist/docs/reference/dashboard/api-keys.mdx +37 -0
- package/dist/docs/reference/dashboard/conditions.mdx +42 -0
- package/dist/docs/reference/dashboard/content/asset-library.mdx +63 -0
- package/dist/docs/reference/dashboard/content/content-entries.mdx +44 -0
- package/dist/docs/reference/dashboard/content/layouts.mdx +62 -0
- package/dist/docs/reference/dashboard/content/pages.mdx +35 -0
- package/dist/docs/reference/dashboard/content/sections.mdx +28 -0
- package/dist/docs/reference/dashboard/experiences.mdx +51 -0
- package/dist/docs/reference/dashboard/features.mdx +114 -0
- package/dist/docs/reference/dashboard/fields.mdx +100 -0
- package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +58 -0
- package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +57 -0
- package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +72 -0
- package/dist/docs/reference/dashboard/flow-builder/nodes.md +63 -0
- package/dist/docs/reference/dashboard/projects.mdx +44 -0
- package/dist/docs/reference/dashboard/reports.mdx +43 -0
- package/dist/docs/reference/dashboard/steps.mdx +37 -0
- package/dist/docs/reference/dashboard/team-management.md +29 -0
- package/dist/docs/reference/dashboard/workspace-versioning.mdx +30 -0
- package/dist/docs/reference/dashboard/workspaces.mdx +76 -0
- package/dist/docs/{delivery-api → reference/delivery-api}/experience-content.md +17 -5
- package/dist/docs/reference/delivery-api/index.md +45 -0
- package/dist/docs/reference/delivery-api/preview-caching-crawling.md +79 -0
- package/dist/docs/{delivery-api → reference/delivery-api}/project-config.md +15 -6
- package/dist/docs/reference/glossary.md +173 -0
- package/dist/docs/reference/management-api/authentication.md +74 -0
- package/dist/docs/{api → reference/management-api}/authorization-and-scopes.md +70 -47
- package/dist/docs/reference/management-api/error-handling.md +233 -0
- package/dist/docs/{api → reference/management-api}/pagination.md +36 -20
- package/dist/docs/reference/pickedql/data-sources.md +174 -0
- package/dist/docs/reference/pickedql/dimensions.md +87 -0
- package/dist/docs/{pickedql → reference/pickedql}/filtering.md +17 -6
- package/dist/docs/reference/pickedql/index.md +18 -0
- package/dist/docs/reference/pickedql/schema.md +172 -0
- package/dist/docs/reference/pickedql/virtual-functions.md +237 -0
- package/dist/docs/reference/sdk/actions.md +30 -0
- package/dist/docs/{sdk → reference/sdk}/conditions.md +15 -5
- package/dist/docs/reference/sdk/content-security-policy.md +21 -0
- package/dist/docs/reference/sdk/experiences.md +51 -0
- package/dist/docs/reference/sdk/features.md +233 -0
- package/dist/docs/reference/sdk/fields.md +209 -0
- package/dist/docs/reference/sdk/index.md +68 -0
- package/dist/docs/{sdk → reference/sdk}/plugins/create-experience.md +25 -34
- package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +74 -0
- package/dist/docs/reference/sdk/plugins/index.md +29 -0
- package/dist/docs/{sdk → reference/sdk}/plugins/window-object.md +6 -0
- package/dist/docs/reference/sdk/predicates.md +43 -0
- package/dist/docs/reference/sdk/ssr/index.md +33 -0
- package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +103 -0
- package/dist/docs/reference/sdk/ssr/serialize.md +77 -0
- package/dist/docs/reference/sdk/ssr/slots-and-placements.md +59 -0
- package/dist/docs/reference/sdk/steps.md +87 -0
- package/dist/docs/reference/tools/chrome-extension.md +16 -0
- package/dist/docs/reference/tools/image-optimisation-service.md +104 -0
- package/dist/docs/reference/tools/mcp.md +88 -0
- package/dist/docs/reference/tools/vite-plugin.md +88 -0
- package/dist/docs/tutorials/first-api-call.md +228 -0
- package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +143 -0
- package/dist/docs/tutorials/first-experience.mdx +255 -0
- package/dist/docs/tutorials/first-server-rendered-page.mdx +186 -0
- package/dist/{dom-BwmTHeT7.js → dom-BqcToNL0.js} +1 -3
- package/dist/{dom-CDrHc_j9.cjs → dom-DlLH3FxV.cjs} +1 -1
- package/dist/esm/form/index.js +2 -4
- package/dist/esm/index.js +225 -186
- package/dist/esm/plugins/dom-observer/index.js +1 -1
- package/dist/esm/plugins/dynamic-experiences/index.js +3 -3
- package/dist/esm/preview/index.js +1 -1
- package/dist/esm/server/index.js +33 -31
- package/dist/{experience-instance-DOJShRk5.js → experience-instance-DGk11d8a.js} +3 -3
- package/dist/experience-instance-Dej3P1sE.cjs +1 -0
- package/dist/plugin-CHOVsx7Z.js +287 -0
- package/dist/plugin-DsaGXQHx.cjs +1 -0
- package/dist/{preview-channel-DW9J8t4B.js → preview-channel-CSr96XAo.js} +1 -1
- package/dist/{protocol-DSqOlW2r.js → protocol-C5KkkiZc.js} +1 -1
- package/dist/types/client.d.ts +7 -6
- package/dist/types/data-source/api.d.ts +60 -0
- package/dist/types/data-source/api.d.ts.map +1 -0
- package/dist/types/data-source/provider.d.ts +97 -0
- package/dist/types/data-source/provider.d.ts.map +1 -0
- package/dist/types/entities/action/action.d.ts +5 -4
- package/dist/types/entities/action/action.d.ts.map +1 -1
- package/dist/types/entities/component/component.d.ts +6 -5
- package/dist/types/entities/component/component.d.ts.map +1 -1
- package/dist/types/entities/condition/condition.d.ts +5 -5
- package/dist/types/entities/content/content.d.ts +4 -3
- package/dist/types/entities/experience/experience.d.ts +11 -10
- package/dist/types/entities/experience/experience.d.ts.map +1 -1
- package/dist/types/entities/experience-instance/experience-instance.d.ts +10 -9
- package/dist/types/entities/feature/feature.d.ts +19 -2
- package/dist/types/entities/feature/feature.d.ts.map +1 -1
- package/dist/types/entities/field/field.d.ts +7 -6
- package/dist/types/entities/framework/framework.d.ts +7 -6
- package/dist/types/entities/framework/framework.d.ts.map +1 -1
- package/dist/types/entities/history/history.d.ts +6 -6
- package/dist/types/entities/plugin/plugin.d.ts +3 -2
- package/dist/types/entities/plugin/plugin.d.ts.map +1 -1
- package/dist/types/entities/predicate/predicate.d.ts +4 -3
- package/dist/types/entities/predicate/predicate.d.ts.map +1 -1
- package/dist/types/entities/response/response-validation.d.ts +3 -2
- package/dist/types/entities/response/response.d.ts +12 -11
- package/dist/types/entities/session/session.d.ts +2 -1
- package/dist/types/entities/step/step.d.ts +6 -5
- package/dist/types/exports.d.ts +2 -1
- package/dist/types/exports.d.ts.map +1 -1
- package/dist/types/form/build-responses.d.ts +2 -1
- package/dist/types/form/create-field-evaluator.d.ts +4 -3
- package/dist/types/form/create-field-validation.d.ts +5 -4
- package/dist/types/form/create-form.d.ts +7 -6
- package/dist/types/form/create-submit-pipeline.d.ts +7 -6
- package/dist/types/form/get-step-fields.d.ts +3 -2
- package/dist/types/lifecycle/condition-selection.d.ts +14 -4
- package/dist/types/lifecycle/lifecycle.d.ts +4 -3
- package/dist/types/lifecycle/rules-logic.d.ts +4 -3
- package/dist/types/lifecycle/state-snapshot.d.ts +4 -3
- package/dist/types/picked.d.ts +79 -62
- package/dist/types/picked.d.ts.map +1 -1
- package/dist/types/ping.d.ts +1 -1
- package/dist/types/ping.d.ts.map +1 -1
- package/dist/types/plugins/create-experience/create-experience.d.ts +9 -8
- package/dist/types/plugins/create-experience/create-experience.d.ts.map +1 -1
- package/dist/types/plugins/create-experience/plugin.d.ts +3 -2
- package/dist/types/plugins/create-experience/plugin.d.ts.map +1 -1
- package/dist/types/plugins/create-experience/serialization.d.ts.map +1 -1
- package/dist/types/plugins/dom-observer/plugin.d.ts +1 -1
- package/dist/types/plugins/dynamic-experiences/hash.d.ts +40 -5
- package/dist/types/plugins/dynamic-experiences/hash.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/index.d.ts +2 -0
- package/dist/types/plugins/dynamic-experiences/index.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/plugin.d.ts +4 -36
- package/dist/types/plugins/dynamic-experiences/plugin.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/types.d.ts +42 -11
- package/dist/types/plugins/dynamic-experiences/types.d.ts.map +1 -1
- package/dist/types/plugins/experience-browser-storage/plugin.d.ts +1 -1
- package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
- package/dist/types/plugins/history-browser-storage/plugin.d.ts +1 -1
- package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
- package/dist/types/plugins/responses-browser-storage/plugin.d.ts +1 -1
- package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
- package/dist/types/plugins/responses-indexeddb/plugin.d.ts +1 -1
- package/dist/types/plugins/single-page-app/plugin.d.ts +1 -1
- package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
- package/dist/types/plugins/web-components/plugin.d.ts +2 -1
- package/dist/types/plugins/window-object/plugin.d.ts +2 -2
- package/dist/types/preview-channel.d.ts +5 -1
- package/dist/types/preview-receiver/index.d.ts +18 -1
- package/dist/types/preview-receiver/protocol.d.ts +10 -1
- package/dist/types/server/index.d.ts +3 -3
- package/dist/types/server/serialize.d.ts +8 -2
- package/dist/types/server/serialize.d.ts.map +1 -1
- package/dist/types/utils/dom.d.ts +2 -1
- package/dist/types/utils/events.d.ts +6 -6
- package/dist/types/utils/events.d.ts.map +1 -1
- package/dist/types/utils/global-obj.d.ts +1 -1
- package/dist/types/utils/global-obj.d.ts.map +1 -1
- package/dist/types/utils/id.d.ts.map +1 -1
- package/dist/types/utils/logger.d.ts +2 -1
- package/dist/types/utils/logger.d.ts.map +1 -1
- package/dist/types/utils/node-tree/get-next-node-from-action.d.ts +2 -1
- package/dist/types/utils/node-tree/get-next-node-from-condition.d.ts +2 -1
- package/dist/types/utils/node-tree/get-next-node.d.ts +1 -1
- package/dist/types/utils/node-tree/get-next-node.d.ts.map +1 -1
- package/dist/types/utils/node-tree/get-origin-node.d.ts +1 -1
- package/dist/types/utils/node-tree/get-origin-node.d.ts.map +1 -1
- package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts +1 -1
- package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts.map +1 -1
- package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts +1 -1
- package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts.map +1 -1
- package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts +1 -1
- package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts.map +1 -1
- package/dist/types/utils/nodes.d.ts +1 -1
- package/dist/types/utils/picked-config.d.ts +2 -1
- package/dist/types/utils/rehydrate-scripts.d.ts +6 -0
- package/dist/types/utils/rehydrate-scripts.d.ts.map +1 -1
- package/dist/types/utils/rules-logic.d.ts +6 -2
- package/dist/types/utils/storage.d.ts +1 -1
- package/dist/types/utils/storage.d.ts.map +1 -1
- package/package.json +22 -23
- package/dist/api-CPL40b7A.js +0 -40
- package/dist/api-Dz5rgRgQ.cjs +0 -1
- package/dist/docs/actions.mdx +0 -78
- package/dist/docs/api/authentication.md +0 -376
- package/dist/docs/api/error-handling.md +0 -211
- package/dist/docs/api/index.md +0 -197
- package/dist/docs/api-keys.mdx +0 -40
- package/dist/docs/chrome-extension.md +0 -51
- package/dist/docs/conditions.mdx +0 -59
- package/dist/docs/content/asset-library.mdx +0 -93
- package/dist/docs/content/content-entries.mdx +0 -30
- package/dist/docs/content/layouts.mdx +0 -70
- package/dist/docs/content/pages.mdx +0 -67
- package/dist/docs/content/sections.mdx +0 -33
- package/dist/docs/delivery-api/index.md +0 -46
- package/dist/docs/delivery-api/preview-caching-crawling.md +0 -59
- package/dist/docs/experiences.mdx +0 -42
- package/dist/docs/features.mdx +0 -58
- package/dist/docs/fields.mdx +0 -79
- package/dist/docs/flow-builder/building-flows.md +0 -61
- package/dist/docs/flow-builder/condition-builder.md +0 -54
- package/dist/docs/flow-builder/keyboard-shortcuts.md +0 -66
- package/dist/docs/flow-builder/nodes.md +0 -43
- package/dist/docs/flow-builder/overview.mdx +0 -50
- package/dist/docs/gtm-template.md +0 -69
- package/dist/docs/guides/build-a-personalized-page.mdx +0 -143
- package/dist/docs/image-optimisation-service.md +0 -80
- package/dist/docs/mcp.md +0 -120
- package/dist/docs/pickedql/data-sources.md +0 -145
- package/dist/docs/pickedql/dimensions.md +0 -65
- package/dist/docs/pickedql/index.md +0 -36
- package/dist/docs/pickedql/schema.md +0 -156
- package/dist/docs/pickedql/virtual-functions.md +0 -204
- package/dist/docs/projects.mdx +0 -37
- package/dist/docs/reports.mdx +0 -18
- package/dist/docs/sdk/actions.md +0 -66
- package/dist/docs/sdk/content-security-policy.md +0 -32
- package/dist/docs/sdk/experiences.md +0 -46
- package/dist/docs/sdk/features.md +0 -212
- package/dist/docs/sdk/fields.md +0 -263
- package/dist/docs/sdk/index.md +0 -83
- package/dist/docs/sdk/plugins/dynamic-experiences.md +0 -58
- package/dist/docs/sdk/plugins/index.md +0 -9
- package/dist/docs/sdk/predicates.md +0 -112
- package/dist/docs/sdk/ssr/index.md +0 -62
- package/dist/docs/sdk/ssr/rendering-and-hydration.md +0 -141
- package/dist/docs/sdk/ssr/serialize.md +0 -86
- package/dist/docs/sdk/ssr/slots-and-placements.md +0 -35
- package/dist/docs/sdk/steps.md +0 -434
- package/dist/docs/steps.mdx +0 -44
- package/dist/docs/team-management.md +0 -40
- package/dist/docs/vite-plugin.md +0 -82
- package/dist/docs/workspace-versioning.mdx +0 -28
- package/dist/docs/workspaces.mdx +0 -102
- package/dist/experience-instance-DurC3pE-.cjs +0 -1
- package/dist/plugin-CFXwbXeM.js +0 -247
- package/dist/plugin-m4qekgtA.cjs +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Server Snapshot
|
|
7
|
+
|
|
8
|
+
`serialize()` finds which experiences match a URL and reads their content on the
|
|
9
|
+
server. It returns a snapshot as plain JSON, and you pass that snapshot to the
|
|
10
|
+
client.
|
|
11
|
+
|
|
12
|
+
## The `serialize(client, params)` function
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { createClient } from '@picked/client'
|
|
16
|
+
import { serialize } from '@picked/client/server'
|
|
17
|
+
|
|
18
|
+
const client = createClient(options)
|
|
19
|
+
|
|
20
|
+
const snapshot = await serialize(client, {
|
|
21
|
+
projectConfig,
|
|
22
|
+
attributes: { location: { pathname: '/promo' } },
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`serialize()` does this. It registers the project configuration on the client at once. It
|
|
27
|
+
evaluates the condition of each experience against `attributes.location`. It reads
|
|
28
|
+
the content for each experience whose steps point at layout content. It removes the
|
|
29
|
+
duplicate content blobs, which it finds by their IDs. It then returns a
|
|
30
|
+
`PickedSnapshot`.
|
|
31
|
+
|
|
32
|
+
Give `serialize()` one client for each request. It does not support two calls at the
|
|
33
|
+
same time on one client.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
serialize(client: Picked, params: SerializeParams): Promise<PickedSnapshot>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Parameters
|
|
40
|
+
|
|
41
|
+
| Parameter | Type | Default | Description |
|
|
42
|
+
| --- | --- | --- | --- |
|
|
43
|
+
| `projectConfig` | `ProjectConfig` | required | The published configuration, or the preview configuration, to register and choose against. |
|
|
44
|
+
| `attributes.location` | `Partial<SerializeLocation>` | none | The URL fields that go into the selection context, such as `pathname`. |
|
|
45
|
+
| `getContent` | `SerializeGetContent` | runtime API | Your own function to read content, in place of the runtime API. |
|
|
46
|
+
| `previewToken` | `string` | none | The SDK sends this with the content request, so that preview content resolves during a preview render. |
|
|
47
|
+
| `timeoutMs` | `number` | `10000` | The limit for each content request. After the limit, the SDK skips that blob and continues. |
|
|
48
|
+
|
|
49
|
+
`SerializeLocation` carries the URL fields `href`, `pathname`, `search`, `hostname`,
|
|
50
|
+
`origin`, `protocol`, `port`, `host`, and `hash`. Pass only the fields that your
|
|
51
|
+
conditions read.
|
|
52
|
+
|
|
53
|
+
## The snapshot
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
interface PickedSnapshot {
|
|
57
|
+
versionId: string | null
|
|
58
|
+
projectConfig: ProjectConfig
|
|
59
|
+
content: ContentBlob[]
|
|
60
|
+
conditionResults: Record<string, boolean>
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
| Field | Description |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `versionId` | The project version that the snapshot was chosen against. It is `null` when the version is not known, for example in a preview. |
|
|
67
|
+
| `projectConfig` | The options that the server chose with. They travel to the client, so that the client renders against exactly the same options. |
|
|
68
|
+
| `content` | The content blobs for the chosen experiences, with the duplicates removed. |
|
|
69
|
+
| `conditionResults` | The condition results that the server kept, under a key made from the rule hash. The client then reuses the choice of the server. |
|
|
70
|
+
|
|
71
|
+
The snapshot is plain JSON. Write it into your HTML response with `JSON.stringify`
|
|
72
|
+
and read it back on the client.
|
|
73
|
+
|
|
74
|
+
## Related
|
|
75
|
+
|
|
76
|
+
- [How to server-render a page](/how-to/server-render-a-page)
|
|
77
|
+
- [How to render an unpublished preview](/how-to/render-an-unpublished-preview)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Slots and Placements
|
|
7
|
+
|
|
8
|
+
A slot is a named mount point. `<ExperienceSlot name="page" />` renders every
|
|
9
|
+
experience that points at that slot and whose condition matches.
|
|
10
|
+
|
|
11
|
+
## What a slot is
|
|
12
|
+
|
|
13
|
+
The `name` of a slot points at the `.picked-slot-<name>` selector. So
|
|
14
|
+
`<ExperienceSlot name="page" />` renders every experience with the target selector
|
|
15
|
+
`.picked-slot-page`, when the condition of that experience is active.
|
|
16
|
+
|
|
17
|
+
The slot reads the active state of each experience from the seeded snapshot. It
|
|
18
|
+
therefore renders at once, both in server-side rendering and at the first paint of
|
|
19
|
+
the hydration.
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
<ExperienceSlot name="page" />
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Point an experience at a slot
|
|
26
|
+
|
|
27
|
+
Set the target selector of the experience to `.picked-slot-<name>`. An experience
|
|
28
|
+
that points at `.picked-slot-page` renders into `<ExperienceSlot name="page" />`. The
|
|
29
|
+
name of the slot and the end of the selector must match.
|
|
30
|
+
|
|
31
|
+
## Placement order
|
|
32
|
+
|
|
33
|
+
When more than one experience points at the same slot, they render in this placement
|
|
34
|
+
order:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
replace -> before -> prepend -> append -> after
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`replace` wins. An active experience with the `replace` placement renders alone, and
|
|
41
|
+
it replaces every other match in the slot. In every other case each active experience
|
|
42
|
+
renders, in placement order.
|
|
43
|
+
|
|
44
|
+
## More than one experience in one slot
|
|
45
|
+
|
|
46
|
+
The slot collects each experience that points at its selector. It drops each one
|
|
47
|
+
whose condition is not active. It then sorts the rest into placement order. When a `replace`
|
|
48
|
+
experience is among the active ones, only that experience renders. With no active
|
|
49
|
+
`replace`, the slot renders every active experience in the order `before`, `prepend`,
|
|
50
|
+
`append`, `after`.
|
|
51
|
+
|
|
52
|
+
One Page can therefore take a whole slot with `replace`, while another slot holds
|
|
53
|
+
several experiences that use the other placements. A condition decides which
|
|
54
|
+
experiences are active. See [Conditions](/reference/dashboard/conditions).
|
|
55
|
+
|
|
56
|
+
## Related
|
|
57
|
+
|
|
58
|
+
- [About server-side rendering](/explanation/why-server-side-rendering) — why placements
|
|
59
|
+
have an order.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Steps
|
|
7
|
+
|
|
8
|
+
Render your steps with `<StepRouter>` and `<Step>` from `@picked/react` or
|
|
9
|
+
`@picked/svelte`. Reach the active step through `useStep()` or `getStep()`.
|
|
10
|
+
|
|
11
|
+
## Reach the step context
|
|
12
|
+
|
|
13
|
+
Inside a `Step` component, or inside any component that a `Step` renders, call
|
|
14
|
+
`getStep()` or `useStep()` to reach the reactive context of the step:
|
|
15
|
+
|
|
16
|
+
:::code-group
|
|
17
|
+
|
|
18
|
+
```tsx [React]
|
|
19
|
+
import { useStep } from '@picked/react/hooks'
|
|
20
|
+
import { useUnit } from 'effector-react'
|
|
21
|
+
|
|
22
|
+
function ContactForm() {
|
|
23
|
+
const { step, fields } = useStep()
|
|
24
|
+
const currentStep = useUnit(step)
|
|
25
|
+
const currentFields = useUnit(fields)
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<h1>{currentStep.label}</h1>
|
|
30
|
+
|
|
31
|
+
{currentFields.map((field) => (
|
|
32
|
+
<div key={field.id}>
|
|
33
|
+
<label>{field.label}</label>
|
|
34
|
+
<input
|
|
35
|
+
name={field.id}
|
|
36
|
+
value={field.value ?? ''}
|
|
37
|
+
onChange={field.onChange}
|
|
38
|
+
onBlur={field.onBlur}
|
|
39
|
+
/>
|
|
40
|
+
{field.error && field.touched && <p className="error">{field.error.userMessage}</p>}
|
|
41
|
+
</div>
|
|
42
|
+
))}
|
|
43
|
+
</>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```svelte [Svelte]
|
|
49
|
+
<script lang="ts">
|
|
50
|
+
import { getStep } from '@picked/svelte/hooks'
|
|
51
|
+
|
|
52
|
+
const { step, fields } = getStep()
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<h1>{$step.label}</h1>
|
|
56
|
+
|
|
57
|
+
{#each $fields as field}
|
|
58
|
+
<label>{field.label}</label>
|
|
59
|
+
<input
|
|
60
|
+
name={field.id}
|
|
61
|
+
value={field.value ?? ''}
|
|
62
|
+
onchange={field.onChange}
|
|
63
|
+
onblur={field.onBlur}
|
|
64
|
+
/>
|
|
65
|
+
{#if field.error && field.touched}
|
|
66
|
+
<p class="error">{field.error.userMessage}</p>
|
|
67
|
+
{/if}
|
|
68
|
+
{/each}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
:::
|
|
72
|
+
|
|
73
|
+
`getStep()` in Svelte, and `useStep()` in React, return a `StepContext` with these
|
|
74
|
+
properties:
|
|
75
|
+
|
|
76
|
+
| Property | Type | Description |
|
|
77
|
+
| ---------- | --------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
78
|
+
| `step` | `Store<ExperienceStep>` | A reactive store that holds the `id` and the `label` of the step |
|
|
79
|
+
| `fields` | `Store<FormField[]>` | A reactive store of the fields, with their current values, errors, and handlers |
|
|
80
|
+
| `isActive` | `Store<boolean>` (Svelte) / `boolean` (React) | Whether the router holds this step as the active one |
|
|
81
|
+
| `form` | Object | The handlers for a form submission. See [Forms](#forms). |
|
|
82
|
+
|
|
83
|
+
## Related
|
|
84
|
+
|
|
85
|
+
- [How to render a step form](/how-to/render-a-step-form)
|
|
86
|
+
- [How to run code on a form submission](/how-to/run-code-on-a-form-submission)
|
|
87
|
+
- [About how Picked works](/explanation/how-picked-works) — why a flow is a graph.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Chrome Extension
|
|
7
|
+
|
|
8
|
+
The extension for the Picked Developer Tools adds a Picked panel to Chrome DevTools.
|
|
9
|
+
Use the panel to check and debug your Picked integration on any page that runs the
|
|
10
|
+
SDK.
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
## Related
|
|
15
|
+
|
|
16
|
+
- [How to debug with the Chrome extension](/how-to/debug-with-the-chrome-extension)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Image optimisation service
|
|
7
|
+
|
|
8
|
+
The Picked service for image optimisation is a hosted endpoint at
|
|
9
|
+
`https://img.picked-content.com`. It reads an image from an allowed source domain and
|
|
10
|
+
resizes it. It then encodes the image again to a modern format, WebP or AVIF, and
|
|
11
|
+
caches the result.
|
|
12
|
+
|
|
13
|
+
## Endpoint
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
GET https://img.picked-content.com/_next/image?url={source}&w={width}&q={quality}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| Parameter | Description |
|
|
20
|
+
|-----------|-------------|
|
|
21
|
+
| `url` | The URL of the source image, URL-encoded. It must point at an allowed source domain. See below. |
|
|
22
|
+
| `w` | The width in pixels. It must be one of the supported widths. |
|
|
23
|
+
| `q` | The quality: `25`, `50`, `75`, or `100`. |
|
|
24
|
+
|
|
25
|
+
The service chooses the response format. When the browser advertises `image/avif` or
|
|
26
|
+
`image/webp` in its `Accept` header, the response uses that format. If it does not,
|
|
27
|
+
the response uses the source format.
|
|
28
|
+
|
|
29
|
+
## Allowed source domains
|
|
30
|
+
|
|
31
|
+
The service reads only from these hostnames:
|
|
32
|
+
|
|
33
|
+
- `**.picked.app`
|
|
34
|
+
|
|
35
|
+
A request with a `url` parameter for any other hostname returns `400 Bad Request`.
|
|
36
|
+
|
|
37
|
+
## Supported widths
|
|
38
|
+
|
|
39
|
+
Device sizes, for a responsive image that spans the width of the viewport:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
640, 750, 828, 1080, 1200, 1920, 2048, 3840
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Image sizes, for a UI element of fixed size such as an icon, an avatar, or a
|
|
46
|
+
thumbnail:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
16, 32, 48, 64, 96, 128, 256, 384
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
A request with any other width returns `400 Bad Request`. Choose the smallest width
|
|
53
|
+
that covers the size you render at the device pixel ratio of the visitor.
|
|
54
|
+
|
|
55
|
+
## Supported qualities
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
25, 50, 75, 100
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
A lower value reduces the bandwidth by a large amount. `75` is a good default for
|
|
62
|
+
most images. Use `25` or `50` for a thumbnail on a slow network.
|
|
63
|
+
|
|
64
|
+
## Responsive images
|
|
65
|
+
|
|
66
|
+
Use the endpoint together with the standard `srcset` attribute. The browser then
|
|
67
|
+
picks the correct width for each viewport:
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<img
|
|
71
|
+
src="https://img.picked-content.com/_next/image?url=https%3A%2F%2Fcdn.picked.app%2Fhero.png&w=1080&q=75"
|
|
72
|
+
srcset="
|
|
73
|
+
https://img.picked-content.com/_next/image?url=https%3A%2F%2Fcdn.picked.app%2Fhero.png&w=640&q=75 640w,
|
|
74
|
+
https://img.picked-content.com/_next/image?url=https%3A%2F%2Fcdn.picked.app%2Fhero.png&w=1080&q=75 1080w,
|
|
75
|
+
https://img.picked-content.com/_next/image?url=https%3A%2F%2Fcdn.picked.app%2Fhero.png&w=1920&q=75 1920w
|
|
76
|
+
"
|
|
77
|
+
sizes="(max-width: 768px) 100vw, 720px"
|
|
78
|
+
alt="..."
|
|
79
|
+
/>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Cache
|
|
83
|
+
|
|
84
|
+
The upstream CDN caches each optimised response. The smallest cache TTL is 60
|
|
85
|
+
seconds. The real lifetime depends on the eviction policy of the CDN. When you change
|
|
86
|
+
the source image at the same URL, the optimised copy stays in the cache for at least
|
|
87
|
+
that time.
|
|
88
|
+
|
|
89
|
+
## Security
|
|
90
|
+
|
|
91
|
+
- The service does not optimise an SVG source. A request for an SVG returns the
|
|
92
|
+
original bytes when the source is allowed. The service never runs an embedded
|
|
93
|
+
script.
|
|
94
|
+
- Each optimised response carries a strict `Content-Security-Policy`
|
|
95
|
+
(`default-src *; script-src 'none'; sandbox;`). A compromised source therefore
|
|
96
|
+
cannot run a script in the browser that shows the image.
|
|
97
|
+
- The response uses `Content-Disposition: inline`, and never `attachment`.
|
|
98
|
+
|
|
99
|
+
## Related
|
|
100
|
+
|
|
101
|
+
- [Asset library](/reference/dashboard/content/asset-library) — where the images come
|
|
102
|
+
from.
|
|
103
|
+
- [Content Security Policy](/reference/sdk/content-security-policy) — the `img-src`
|
|
104
|
+
entry this service needs.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# MCP server
|
|
7
|
+
|
|
8
|
+
Control your Picked workspace from an AI tool that writes code, with the Model
|
|
9
|
+
Context Protocol (MCP).
|
|
10
|
+
|
|
11
|
+
## Tools
|
|
12
|
+
|
|
13
|
+
### Discovery
|
|
14
|
+
|
|
15
|
+
| Tool | Description |
|
|
16
|
+
| ------------------------ | ------------------------------------------------------------ |
|
|
17
|
+
| `list_projects` | Lists your organizations and projects |
|
|
18
|
+
| `get_workspace_overview` | Reads the full workspace state |
|
|
19
|
+
| `get_schema_info` | Reads the documentation for Picked concepts and the data model |
|
|
20
|
+
| `get_picked_docs` | Reads the complete Picked documentation, as text for an agent |
|
|
21
|
+
|
|
22
|
+
### Experiences
|
|
23
|
+
|
|
24
|
+
| Tool | Description |
|
|
25
|
+
| ------------------------ | ----------------------------------------------------------------------------------------- |
|
|
26
|
+
| `create_experience` | Creates an experience |
|
|
27
|
+
| `get_experience` | Reads an experience, with its flow graph |
|
|
28
|
+
| `list_experiences` | Lists your experiences |
|
|
29
|
+
| `update_experience_flow` | Creates, updates, or deletes steps, conditions, actions, fields, nodes, and edges as one operation |
|
|
30
|
+
|
|
31
|
+
### Steps, fields, conditions, and actions
|
|
32
|
+
|
|
33
|
+
| Tool | Description |
|
|
34
|
+
| ----------------------------------- | --------------- |
|
|
35
|
+
| `get_step` / `list_steps` | Read steps |
|
|
36
|
+
| `get_field` / `list_fields` | Read fields |
|
|
37
|
+
| `get_condition` / `list_conditions` | Read conditions |
|
|
38
|
+
| `get_action` / `list_actions` | Read actions |
|
|
39
|
+
|
|
40
|
+
### Feature flags
|
|
41
|
+
|
|
42
|
+
| Tool | Description |
|
|
43
|
+
| ---------------- | ---------------------------------------------------- |
|
|
44
|
+
| `create_feature` | Creates a feature flag |
|
|
45
|
+
| `get_feature` | Reads a feature flag |
|
|
46
|
+
| `list_features` | Lists your feature flags |
|
|
47
|
+
| `update_feature` | Updates the name, description, state, or weight |
|
|
48
|
+
|
|
49
|
+
### Analytics
|
|
50
|
+
|
|
51
|
+
| Tool | Description |
|
|
52
|
+
| ---------------- | ---------------------------------------------------------------- |
|
|
53
|
+
| `query_pickedql` | Runs a PickedQL analytics query and returns the rows as a table |
|
|
54
|
+
|
|
55
|
+
Call `get_schema_info` with the topic `pickedql` to see the tables, the virtual
|
|
56
|
+
functions, and the dimension columns before you write a query.
|
|
57
|
+
|
|
58
|
+
### Publish
|
|
59
|
+
|
|
60
|
+
| Tool | Description |
|
|
61
|
+
| ------------------- | ---------------------------------------------- |
|
|
62
|
+
| `get_preview_url` | Makes a preview URL for your unpublished work |
|
|
63
|
+
| `publish_workspace` | Publishes the workspace |
|
|
64
|
+
|
|
65
|
+
## Example prompts
|
|
66
|
+
|
|
67
|
+
- "List my Picked projects and show me the options on each one"
|
|
68
|
+
- "Create a feature flag called 'new-checkout' at 50% traffic"
|
|
69
|
+
- "Create an experience with a step that collects an email address"
|
|
70
|
+
- "Show me control and variant users by the device type for the last 30 days"
|
|
71
|
+
- "Make a preview URL for my workspace on `https://example.com`"
|
|
72
|
+
|
|
73
|
+
## Tips
|
|
74
|
+
|
|
75
|
+
- Ask your agent for a list of your projects first. Then ask it to read your
|
|
76
|
+
workspace and report the options on each record.
|
|
77
|
+
- For a large experience, ask your agent about flow graphs and JSON Logic. The agent
|
|
78
|
+
can read the documentation for you.
|
|
79
|
+
- An update to an experience flow is atomic. Your agent can create steps, fields,
|
|
80
|
+
nodes, and edges in one operation.
|
|
81
|
+
- See a preview of your work on your site before you publish, to check that each page
|
|
82
|
+
is correct.
|
|
83
|
+
- Ask your agent to run a PickedQL query on your analytics data. The agent can read
|
|
84
|
+
the schema, write the SQL, and explain the rows.
|
|
85
|
+
|
|
86
|
+
## Related
|
|
87
|
+
|
|
88
|
+
- [How to connect the MCP server](/how-to/connect-the-mcp-server)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vite Plugin
|
|
7
|
+
|
|
8
|
+
`@picked/vite-plugin-picked` adds Picked to your Vite project. It reads the options
|
|
9
|
+
of your project at build time. It then injects them through the Vite `define`
|
|
10
|
+
option, so the SDK makes no API request at runtime. In development it also serves a
|
|
11
|
+
launcher page. On that page you can see a preview of an experience with your own
|
|
12
|
+
feature flag values.
|
|
13
|
+
|
|
14
|
+
## How it works
|
|
15
|
+
|
|
16
|
+
### Build-time config injection
|
|
17
|
+
|
|
18
|
+
When Vite starts, in both `dev` and `build`, the plugin does this:
|
|
19
|
+
|
|
20
|
+
1. It reads the configuration of your project from the Picked API.
|
|
21
|
+
2. It embeds those options in your bundle.
|
|
22
|
+
3. The SDK reads the embedded configuration at runtime and makes no network request.
|
|
23
|
+
|
|
24
|
+
When a preview token is there at runtime, the SDK ignores the embedded configuration and
|
|
25
|
+
reads fresh data from the API.
|
|
26
|
+
|
|
27
|
+
### Preload of the data file
|
|
28
|
+
|
|
29
|
+
Vite puts the options of your project in their own JavaScript file. For each HTML page
|
|
30
|
+
in your build, the plugin adds a `<link rel="modulepreload">` for that file. The
|
|
31
|
+
browser then gets it while it reads the page, and not later when the SDK starts.
|
|
32
|
+
|
|
33
|
+
The CMS content of an experience stays in its own file and gets no preload. The
|
|
34
|
+
browser gets it only when an experience needs it.
|
|
35
|
+
|
|
36
|
+
Some applications make their HTML from the code, and not from an HTML file in your
|
|
37
|
+
project. React Router in server mode is one of these. Such a build has no page for the
|
|
38
|
+
plugin to add the link to. Add this line to the code that runs in the browser instead:
|
|
39
|
+
|
|
40
|
+
:::code-group
|
|
41
|
+
|
|
42
|
+
```ts [entry.client.ts]
|
|
43
|
+
import 'virtual:picked/data'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
:::
|
|
47
|
+
|
|
48
|
+
Your framework then sees the file in its own list and adds the preload for you.
|
|
49
|
+
|
|
50
|
+
### Dev launcher
|
|
51
|
+
|
|
52
|
+
In development, the plugin serves an HTML page at `/`. On that page you can:
|
|
53
|
+
|
|
54
|
+
- see every feature flag in your project with its current state;
|
|
55
|
+
- turn a feature flag on or off for a local test;
|
|
56
|
+
- see a preview of an experience with your own feature flag values.
|
|
57
|
+
|
|
58
|
+
After the dev server starts, the launcher URL appears next to the Vite output:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
➜ Picked: http://localhost:5173/
|
|
62
|
+
➜ Local: http://localhost:5173/
|
|
63
|
+
➜ Network: use --host to expose
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Options
|
|
67
|
+
|
|
68
|
+
| Option | Type | Default | Description |
|
|
69
|
+
| ---------------- | --------- | ---------------------------- | -------------------------------------------------------- |
|
|
70
|
+
| `projectId` | `string` | — | **Required.** The ID of your Picked project. |
|
|
71
|
+
| `apiUrl` | `string` | `https://api.picked.app` | Your own API URL, for a self-hosted or local API. |
|
|
72
|
+
| `disableLauncher`| `boolean` | `false` | Turns the launcher page off in both dev and build output.|
|
|
73
|
+
|
|
74
|
+
## Build output
|
|
75
|
+
|
|
76
|
+
For a production build, `vite build`, the plugin writes an `index.html` file that
|
|
77
|
+
holds the launcher page. Set `disableLauncher` to stop this. The file lets you deploy
|
|
78
|
+
the launcher next to your application, so that a stakeholder can see a preview.
|
|
79
|
+
|
|
80
|
+
The plugin writes that file only when your build made no `index.html` of its own. An
|
|
81
|
+
application that has an HTML entry keeps its own page at the root of the output.
|
|
82
|
+
|
|
83
|
+
The plugin also writes a `.picked` directory next to your Vite `root`. It holds the
|
|
84
|
+
options of your project and the CMS content of each experience.
|
|
85
|
+
|
|
86
|
+
## Related
|
|
87
|
+
|
|
88
|
+
- [How to install the Vite plugin](/how-to/install-the-vite-plugin)
|