picked 0.0.101-next.2 → 0.0.101
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/README.md +27 -12
- package/docs/explanation/conditions-and-the-logic-engine.md +94 -0
- package/docs/explanation/content-references.md +99 -0
- package/docs/explanation/feature-flag-allocation.md +218 -0
- package/docs/explanation/how-picked-works.md +124 -0
- package/docs/explanation/how-pickedql-works.md +76 -0
- package/docs/explanation/pages-and-flows.md +64 -0
- package/docs/explanation/the-content-model.md +87 -0
- package/docs/explanation/the-two-apis.md +68 -0
- package/docs/explanation/why-server-side-rendering.md +76 -0
- package/docs/explanation/workspaces-and-versions.md +71 -0
- package/docs/how-to/add-a-step-field-or-action.md +56 -0
- package/docs/how-to/analytics/index.md +324 -0
- package/docs/how-to/archive-or-delete-a-workspace.md +59 -0
- package/docs/how-to/authenticate-the-cli.md +101 -0
- package/docs/how-to/authenticate-with-a-magic-link.md +56 -0
- package/docs/how-to/authenticate-with-a-password.md +68 -0
- package/docs/how-to/authenticate-with-an-api-key.md +60 -0
- package/docs/how-to/authenticate-with-oauth.md +49 -0
- package/docs/how-to/build-a-flow.md +106 -0
- package/docs/how-to/call-an-external-api-from-a-workflow.md +116 -0
- package/docs/how-to/connect-the-mcp-server.md +46 -0
- package/docs/how-to/create-a-content-entry.md +58 -0
- package/docs/how-to/create-a-project.md +40 -0
- package/docs/how-to/create-an-experience.md +51 -0
- package/docs/how-to/create-and-revoke-an-api-key.md +54 -0
- package/docs/how-to/debug-with-the-chrome-extension.md +57 -0
- package/docs/how-to/define-a-page-layout.md +54 -0
- package/docs/how-to/fill-and-publish-a-page.md +82 -0
- package/docs/how-to/install-the-gtm-template.md +84 -0
- package/docs/how-to/install-the-sdk.md +93 -0
- package/docs/how-to/install-the-vite-plugin.md +69 -0
- package/docs/how-to/invite-and-remove-members.md +45 -0
- package/docs/how-to/point-one-entry-at-another.md +75 -0
- package/docs/how-to/preview-a-workspace.md +39 -0
- package/docs/how-to/publish-a-workspace.md +42 -0
- package/docs/how-to/read-a-feature-flag.md +113 -0
- package/docs/how-to/read-a-referenced-entry.md +109 -0
- package/docs/how-to/register-a-component.md +55 -0
- package/docs/how-to/register-an-action-handler.md +85 -0
- package/docs/how-to/register-an-api-that-uses-oauth2.md +107 -0
- package/docs/how-to/render-a-step-form.md +131 -0
- package/docs/how-to/render-an-unpublished-preview.md +41 -0
- package/docs/how-to/retry-a-failed-call-with-a-loop.md +81 -0
- package/docs/how-to/reuse-a-section.md +64 -0
- package/docs/how-to/reuse-a-step-field-or-action.md +39 -0
- package/docs/how-to/roll-back-a-published-version.md +39 -0
- package/docs/how-to/run-an-ab-test.md +59 -0
- package/docs/how-to/run-code-on-a-form-submission.md +125 -0
- package/docs/how-to/server-render-a-page.md +81 -0
- package/docs/how-to/set-a-content-security-policy.md +32 -0
- package/docs/how-to/set-up-mfa.md +126 -0
- package/docs/how-to/switch-workspaces.md +122 -0
- package/docs/how-to/upload-and-use-an-asset.mdx +87 -0
- package/docs/how-to/validate-a-field.md +52 -0
- package/docs/how-to/wait-for-an-action-response.md +182 -0
- package/docs/how-to/write-a-condition.md +57 -0
- package/docs/how-to/write-a-predicate.md +60 -0
- package/docs/index.md +59 -0
- package/docs/reference/dashboard/actions.mdx +65 -0
- package/docs/reference/dashboard/api-keys.mdx +47 -0
- package/docs/reference/dashboard/conditions.mdx +51 -0
- package/docs/reference/dashboard/content/asset-library.mdx +74 -0
- package/docs/reference/dashboard/content/blocks.mdx +66 -0
- package/docs/reference/dashboard/content/content-entries.mdx +109 -0
- package/docs/reference/dashboard/content/models.mdx +119 -0
- package/docs/reference/dashboard/content/pages.mdx +72 -0
- package/docs/reference/dashboard/experiences.mdx +61 -0
- package/docs/reference/dashboard/external-apis.md +182 -0
- package/docs/reference/dashboard/features.mdx +165 -0
- package/docs/reference/dashboard/fields.mdx +120 -0
- package/docs/reference/dashboard/flow-builder/canvas.mdx +58 -0
- package/docs/reference/dashboard/flow-builder/condition-builder.md +69 -0
- package/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +72 -0
- package/docs/reference/dashboard/flow-builder/nodes.md +74 -0
- package/docs/reference/dashboard/labels.md +321 -0
- package/docs/reference/dashboard/lead-search.md +235 -0
- package/docs/reference/dashboard/projects.mdx +53 -0
- package/docs/reference/dashboard/reports.mdx +53 -0
- package/docs/reference/dashboard/steps.mdx +47 -0
- package/docs/reference/dashboard/team-management.md +38 -0
- package/docs/reference/dashboard/workflow-runs.md +157 -0
- package/docs/reference/dashboard/workflow-templates.md +182 -0
- package/docs/reference/dashboard/workflow-test-runs.md +85 -0
- package/docs/reference/dashboard/workspace-versioning.mdx +42 -0
- package/docs/reference/dashboard/workspaces.mdx +91 -0
- package/docs/reference/delivery-api/experience-content.md +152 -0
- package/docs/reference/delivery-api/index.md +45 -0
- package/docs/reference/delivery-api/preview-caching-crawling.md +79 -0
- package/docs/reference/delivery-api/project-config.md +65 -0
- package/docs/reference/delivery-api/workspace-schema.md +107 -0
- package/docs/reference/glossary.md +201 -0
- package/docs/reference/management-api/authentication.md +87 -0
- package/docs/reference/management-api/authorization-and-scopes.md +291 -0
- package/docs/reference/management-api/error-handling.md +232 -0
- package/docs/reference/management-api/pagination.md +192 -0
- package/docs/reference/management-api/schema/action.md +261 -0
- package/docs/reference/management-api/schema/analytics-session.md +363 -0
- package/docs/reference/management-api/schema/analytics.md +73 -0
- package/docs/reference/management-api/schema/api-key.md +170 -0
- package/docs/reference/management-api/schema/auth.md +1177 -0
- package/docs/reference/management-api/schema/cms-fields.md +954 -0
- package/docs/reference/management-api/schema/cms-models.md +1155 -0
- package/docs/reference/management-api/schema/common.md +362 -0
- package/docs/reference/management-api/schema/condition.md +254 -0
- package/docs/reference/management-api/schema/design-system.md +199 -0
- package/docs/reference/management-api/schema/experience.md +1098 -0
- package/docs/reference/management-api/schema/external-api.md +637 -0
- package/docs/reference/management-api/schema/feature.md +350 -0
- package/docs/reference/management-api/schema/feedback.md +103 -0
- package/docs/reference/management-api/schema/field.md +400 -0
- package/docs/reference/management-api/schema/index.md +243 -0
- package/docs/reference/management-api/schema/integration.md +272 -0
- package/docs/reference/management-api/schema/label.md +349 -0
- package/docs/reference/management-api/schema/lead.md +340 -0
- package/docs/reference/management-api/schema/mcp-server.md +299 -0
- package/docs/reference/management-api/schema/metric.md +223 -0
- package/docs/reference/management-api/schema/operation.md +96 -0
- package/docs/reference/management-api/schema/organization.md +749 -0
- package/docs/reference/management-api/schema/project.md +607 -0
- package/docs/reference/management-api/schema/report.md +243 -0
- package/docs/reference/management-api/schema/saved-view.md +288 -0
- package/docs/reference/management-api/schema/shopify.md +795 -0
- package/docs/reference/management-api/schema/step.md +273 -0
- package/docs/reference/management-api/schema/tenant-branding.md +185 -0
- package/docs/reference/management-api/schema/workbench.md +246 -0
- package/docs/reference/management-api/schema/workflow-run.md +263 -0
- package/docs/reference/management-api/schema/workflow.md +1110 -0
- package/docs/reference/management-api/schema/workspace-version.md +823 -0
- package/docs/reference/management-api/schema/workspace.md +917 -0
- package/docs/reference/pickedql/data-sources.md +174 -0
- package/docs/reference/pickedql/dimensions.md +103 -0
- package/docs/reference/pickedql/filtering.md +64 -0
- package/docs/reference/pickedql/index.md +18 -0
- package/docs/reference/pickedql/schema.md +172 -0
- package/docs/reference/pickedql/virtual-functions.md +248 -0
- package/docs/reference/sdk/actions.md +154 -0
- package/docs/reference/sdk/analytics-events.md +453 -0
- package/docs/reference/sdk/conditions.md +147 -0
- package/docs/reference/sdk/content-security-policy.md +21 -0
- package/docs/reference/sdk/content.md +253 -0
- package/docs/reference/sdk/experiences.md +51 -0
- package/docs/reference/sdk/features.md +256 -0
- package/docs/reference/sdk/fields.md +255 -0
- package/docs/reference/sdk/index.md +68 -0
- package/docs/reference/sdk/plugins/create-experience.md +123 -0
- package/docs/reference/sdk/plugins/dynamic-experiences.md +74 -0
- package/docs/reference/sdk/plugins/fingerprintjs.md +39 -0
- package/docs/reference/sdk/plugins/hotjar.md +60 -0
- package/docs/reference/sdk/plugins/index.md +33 -0
- package/docs/reference/sdk/plugins/sentry.md +51 -0
- package/docs/reference/sdk/plugins/shopify.md +109 -0
- package/docs/reference/sdk/plugins/window-object.md +25 -0
- package/docs/reference/sdk/predicates.md +43 -0
- package/docs/reference/sdk/react.md +61 -0
- package/docs/reference/sdk/ssr/index.md +33 -0
- package/docs/reference/sdk/ssr/rendering-and-hydration.md +103 -0
- package/docs/reference/sdk/ssr/serialize.md +80 -0
- package/docs/reference/sdk/ssr/slots-and-placements.md +113 -0
- package/docs/reference/sdk/steps.md +86 -0
- package/docs/reference/sdk/svelte.md +74 -0
- package/docs/reference/sdk/type-generation.md +265 -0
- package/docs/reference/tools/admin-api-client.md +89 -0
- package/docs/reference/tools/chrome-extension.md +16 -0
- package/docs/reference/tools/cli.md +319 -0
- package/docs/reference/tools/delivery-api-client.md +60 -0
- package/docs/reference/tools/image-optimisation-service.md +104 -0
- package/docs/reference/tools/mcp-run.md +121 -0
- package/docs/reference/tools/mcp.md +391 -0
- package/docs/reference/tools/vite-plugin.md +163 -0
- package/docs/tutorials/first-api-call.md +253 -0
- package/docs/tutorials/first-experience-in-the-dashboard.mdx +160 -0
- package/docs/tutorials/first-experience.mdx +254 -0
- package/docs/tutorials/first-server-rendered-page.mdx +186 -0
- package/package.json +8 -7
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to reuse a step, a field, or an action
|
|
7
|
+
|
|
8
|
+
This guide shows you how to use one step, field, action, or condition in more than one
|
|
9
|
+
flow. All four belong to the project, and not to the experience that you made them in.
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
1. Open the flow builder for the second experience.
|
|
14
|
+
2. Find the step, the action, or the condition in the library on the left.
|
|
15
|
+
3. Drag it onto the canvas, or onto a step node for a field.
|
|
16
|
+
|
|
17
|
+
The same one now appears in both flows.
|
|
18
|
+
|
|
19
|
+
:::warning
|
|
20
|
+
A change to the options applies at every place that uses it. Check the other flows before
|
|
21
|
+
you change a shared step, field, action, or condition.
|
|
22
|
+
:::
|
|
23
|
+
|
|
24
|
+
## API and MCP
|
|
25
|
+
|
|
26
|
+
You can also do this task with the [Management API](/reference/management-api/schema), the [MCP server](/reference/tools/mcp), or code that you send to [`picked_run`](/reference/tools/mcp-run).
|
|
27
|
+
|
|
28
|
+
| Task | GraphQL | MCP tool | Run |
|
|
29
|
+
| --- | --- | --- | --- |
|
|
30
|
+
| Find the step, the action, or the condition | [`steps`](/reference/management-api/schema/step#steps), [`actions`](/reference/management-api/schema/action#actions), [`conditions`](/reference/management-api/schema/condition#conditions) | [`list_steps`](/reference/tools/mcp#list_steps), [`list_actions`](/reference/tools/mcp#list_actions), [`list_conditions`](/reference/tools/mcp#list_conditions) | `tools.list_steps({ workspace_id })`, `tools.list_actions({ workspace_id })`, `tools.list_conditions({ workspace_id })` |
|
|
31
|
+
| Add it to the flow of a second experience | [`experienceFlowUpdate`](/reference/management-api/schema/experience#experienceflowupdate) | [`update_experience_flow`](/reference/tools/mcp#update_experience_flow) | `tools.update_experience_flow({ experience_id, workspace_id, create_steps, create_nodes })` |
|
|
32
|
+
| Assign a field to a step | [`stepUpdate`](/reference/management-api/schema/step#stepupdate), [`experienceFlowUpdate`](/reference/management-api/schema/experience#experienceflowupdate) | [`update_experience_flow`](/reference/tools/mcp#update_experience_flow) | `tools.update_experience_flow({ experience_id, workspace_id, update_steps })` |
|
|
33
|
+
| Find the steps that use a field | [`field`](/reference/management-api/schema/field#field) | [`get_field`](/reference/tools/mcp#get_field) | `tools.get_field({ field_id })` |
|
|
34
|
+
|
|
35
|
+
## Related
|
|
36
|
+
|
|
37
|
+
- [Steps](/reference/dashboard/steps) — the step options.
|
|
38
|
+
- [Fields](/reference/dashboard/fields) — the field options.
|
|
39
|
+
- [Actions](/reference/dashboard/actions) — the action options.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to roll back a published version
|
|
7
|
+
|
|
8
|
+
This guide shows you how to make an earlier published version live again. Your current
|
|
9
|
+
draft does not change.
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
1. Open **Publish history** from the project sidebar.
|
|
14
|
+
2. Find the version that you want to restore.
|
|
15
|
+
3. Click **Restore**.
|
|
16
|
+
4. Read the diff preview. It compares the current live version against the one that you
|
|
17
|
+
chose.
|
|
18
|
+
5. Click **Restore this version** to confirm.
|
|
19
|
+
|
|
20
|
+
The restored version is live immediately.
|
|
21
|
+
|
|
22
|
+
## API and MCP
|
|
23
|
+
|
|
24
|
+
You can also do this task with the [Management API](/reference/management-api/schema), the [MCP server](/reference/tools/mcp), or code that you send to [`picked_run`](/reference/tools/mcp-run).
|
|
25
|
+
|
|
26
|
+
| Task | GraphQL | MCP tool | Run |
|
|
27
|
+
| --- | --- | --- | --- |
|
|
28
|
+
| Find the version | [`project`](/reference/management-api/schema/project#project) | [`list_workspace_versions`](/reference/tools/mcp#list_workspace_versions) | `tools.list_workspace_versions({ project_id })` |
|
|
29
|
+
| Read the diff | [`workspaceDiff`](/reference/management-api/schema/workspace-version#workspacediff) | [`compare_workspace_versions`](/reference/tools/mcp#compare_workspace_versions) | `tools.compare_workspace_versions({ base_version_id, compare_version_id })` |
|
|
30
|
+
| Restore the version | [`workspaceVersionPublish`](/reference/management-api/schema/workspace#workspaceversionpublish) | [`guide_workspace_version_publish`](/reference/tools/mcp#guide_workspace_version_publish) | `tools.guide_workspace_version_publish({ workspace_version_id })` |
|
|
31
|
+
|
|
32
|
+
The MCP server does not restore a version. `guide_workspace_version_publish` gives the
|
|
33
|
+
link to the **Publish history** page in the dashboard.
|
|
34
|
+
|
|
35
|
+
## Related
|
|
36
|
+
|
|
37
|
+
- [About workspaces and versions](/explanation/workspaces-and-versions) — why a roll-back
|
|
38
|
+
changes no data.
|
|
39
|
+
- [Publish history](/reference/dashboard/workspace-versioning) — the version list.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to run an A/B test
|
|
7
|
+
|
|
8
|
+
This guide shows you how to split your traffic with a feature flag and read the result in
|
|
9
|
+
your application.
|
|
10
|
+
|
|
11
|
+
Read [About feature flag allocation](/explanation/feature-flag-allocation) first. The
|
|
12
|
+
point at which you read the feature flag decides when a visitor enters the test.
|
|
13
|
+
|
|
14
|
+
## 1. Create the feature flag
|
|
15
|
+
|
|
16
|
+
1. Open your project.
|
|
17
|
+
2. Click **Feature flags** in the sidebar.
|
|
18
|
+
3. Click **New feature flag**.
|
|
19
|
+
4. Enter a name.
|
|
20
|
+
5. Click **Create feature flag**.
|
|
21
|
+
|
|
22
|
+
You cannot change the key after you create the feature flag.
|
|
23
|
+
|
|
24
|
+
## 2. Set the allocation
|
|
25
|
+
|
|
26
|
+
Open the detail page of the feature flag and set these controls:
|
|
27
|
+
|
|
28
|
+
1. Turn **Enabled** on. A feature flag that is off allocates nobody.
|
|
29
|
+
2. Set **Weight** to the percentage of visitors that you want in the test.
|
|
30
|
+
3. Enter a **Description** that says what the feature flag tests.
|
|
31
|
+
|
|
32
|
+
## 3. Read the feature flag in your application
|
|
33
|
+
|
|
34
|
+
See [How to read a feature flag](/how-to/read-a-feature-flag). Read it at the point where
|
|
35
|
+
the decision matters, and not at startup.
|
|
36
|
+
|
|
37
|
+
## 4. Change the weight later
|
|
38
|
+
|
|
39
|
+
1. Change **Weight** on the detail page.
|
|
40
|
+
2. Increment the version.
|
|
41
|
+
|
|
42
|
+
The new weight then applies to a visitor with a cached decision. Leave the version as it
|
|
43
|
+
is to apply the new weight only to a visitor who is not allocated yet.
|
|
44
|
+
|
|
45
|
+
## API and MCP
|
|
46
|
+
|
|
47
|
+
You can also do this task with the [Management API](/reference/management-api/schema), the [MCP server](/reference/tools/mcp), or code that you send to [`picked_run`](/reference/tools/mcp-run).
|
|
48
|
+
|
|
49
|
+
| Task | GraphQL | MCP tool | Run |
|
|
50
|
+
| --- | --- | --- | --- |
|
|
51
|
+
| Create the feature flag | [`featureCreate`](/reference/management-api/schema/feature#featurecreate) | [`create_feature`](/reference/tools/mcp#create_feature) | `tools.create_feature({ workspace_id, name, variants })` |
|
|
52
|
+
| Set the allocation | [`featureUpdate`](/reference/management-api/schema/feature#featureupdate) | [`update_feature`](/reference/tools/mcp#update_feature) | `tools.update_feature({ feature_id, workspace_id, weight })` |
|
|
53
|
+
| Change the weight and increment the version | [`featureUpdate`](/reference/management-api/schema/feature#featureupdate) | [`update_feature`](/reference/tools/mcp#update_feature) | `tools.update_feature({ feature_id, workspace_id, weight, increment_version: true })` |
|
|
54
|
+
|
|
55
|
+
## Related
|
|
56
|
+
|
|
57
|
+
- [About feature flag allocation](/explanation/feature-flag-allocation) — why two feature
|
|
58
|
+
flags at the same weight give four groups, not two.
|
|
59
|
+
- [Feature flags](/reference/dashboard/features) — the controls.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to run code on a form submission
|
|
7
|
+
|
|
8
|
+
This guide shows you how to act on a step submission. Pass your callbacks to `useStep()`
|
|
9
|
+
in React, or to `getStep()` in Svelte.
|
|
10
|
+
|
|
11
|
+
## What the SDK does on submit
|
|
12
|
+
|
|
13
|
+
1. It collects the field values from the HTML form.
|
|
14
|
+
2. It runs each `onBeforeSubmit` callback, one after another.
|
|
15
|
+
3. It checks each required field and each validation rule.
|
|
16
|
+
4. It commits the responses to the experience state.
|
|
17
|
+
5. It fires `form_submit_success` or `form_submit_error` on the event bus.
|
|
18
|
+
6. It runs your `onSuccess` or `onError` callback.
|
|
19
|
+
7. It moves to the next step.
|
|
20
|
+
|
|
21
|
+
## Change the data before it is stored
|
|
22
|
+
|
|
23
|
+
:::code-group
|
|
24
|
+
|
|
25
|
+
```tsx [React]
|
|
26
|
+
const { form } = useStep({
|
|
27
|
+
onBeforeSubmit: async (data) => ({
|
|
28
|
+
...data,
|
|
29
|
+
'email-address': String(data['email-address']).toLowerCase(),
|
|
30
|
+
}),
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```svelte [Svelte]
|
|
35
|
+
<script lang="ts">
|
|
36
|
+
const { form } = getStep({
|
|
37
|
+
onBeforeSubmit: async (data) => ({
|
|
38
|
+
...data,
|
|
39
|
+
'email-address': String(data['email-address']).toLowerCase(),
|
|
40
|
+
}),
|
|
41
|
+
})
|
|
42
|
+
</script>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
:::
|
|
46
|
+
|
|
47
|
+
:::warning
|
|
48
|
+
An `onBeforeSubmit` callback that throws aborts the submit before the SDK commits
|
|
49
|
+
anything, and the step does not advance. Use it for a transform and for a check. Put a
|
|
50
|
+
side effect, such as an analytics call, in `onSuccess`.
|
|
51
|
+
:::
|
|
52
|
+
|
|
53
|
+
## Act on the outcome
|
|
54
|
+
|
|
55
|
+
:::code-group
|
|
56
|
+
|
|
57
|
+
```tsx [React]
|
|
58
|
+
const { form } = useStep({
|
|
59
|
+
onSuccess: ({ data }) => analytics.track('lead_captured', data),
|
|
60
|
+
onError: (errors) => console.error('Validation errors:', errors),
|
|
61
|
+
})
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```svelte [Svelte]
|
|
65
|
+
<script lang="ts">
|
|
66
|
+
const { form } = getStep({
|
|
67
|
+
onSuccess: ({ data }) => analytics.track('lead_captured', data),
|
|
68
|
+
onError: (errors) => console.error('Validation errors:', errors),
|
|
69
|
+
})
|
|
70
|
+
</script>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
:::
|
|
74
|
+
|
|
75
|
+
A callback belongs to the component that passes it, and the SDK releases it when that
|
|
76
|
+
component unmounts. An `onSuccess` callback that throws cannot stop the flow. The SDK
|
|
77
|
+
reports the failure as `form_submit_callback_error`.
|
|
78
|
+
|
|
79
|
+
## Choose the next step yourself
|
|
80
|
+
|
|
81
|
+
Call `stopNavigation()` inside `onSuccess`, then move where you want:
|
|
82
|
+
|
|
83
|
+
:::code-group
|
|
84
|
+
|
|
85
|
+
```tsx [React]
|
|
86
|
+
const experience = useExperience()
|
|
87
|
+
|
|
88
|
+
const { form } = useStep({
|
|
89
|
+
onSuccess: ({ data, stopNavigation }) => {
|
|
90
|
+
stopNavigation()
|
|
91
|
+
if (data['plan-type'] === 'enterprise') {
|
|
92
|
+
experience.goToStepById('enterprise-contact')
|
|
93
|
+
} else {
|
|
94
|
+
experience.goToNextStep()
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```svelte [Svelte]
|
|
101
|
+
<script lang="ts">
|
|
102
|
+
const experience = getExperience()
|
|
103
|
+
|
|
104
|
+
const { form } = getStep({
|
|
105
|
+
onSuccess: ({ data, stopNavigation }) => {
|
|
106
|
+
stopNavigation()
|
|
107
|
+
if (data['plan-type'] === 'enterprise') {
|
|
108
|
+
experience.goToStepById('enterprise-contact')
|
|
109
|
+
} else {
|
|
110
|
+
experience.goToNextStep()
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
})
|
|
114
|
+
</script>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
:::
|
|
118
|
+
|
|
119
|
+
`goToStepById()` takes a step `id`. `goToStepByKey()` takes the key of the step. When no
|
|
120
|
+
step matches, the call does nothing.
|
|
121
|
+
|
|
122
|
+
## Related
|
|
123
|
+
|
|
124
|
+
- [How to render a step form](/how-to/render-a-step-form).
|
|
125
|
+
- [SDK steps](/reference/sdk/steps) — the `form` object.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to server-render a page
|
|
7
|
+
|
|
8
|
+
This guide shows you how to render a Picked Page on your server and hydrate it in the
|
|
9
|
+
browser. You need a published Page and a server that renders React or Svelte.
|
|
10
|
+
|
|
11
|
+
## 1. Make the snapshot
|
|
12
|
+
|
|
13
|
+
Create one client for each request, then call `serialize()`:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createClient } from 'picked'
|
|
17
|
+
import { serialize } from '@picked/client/server'
|
|
18
|
+
|
|
19
|
+
const client = createClient(options)
|
|
20
|
+
|
|
21
|
+
const snapshot = await serialize(client, {
|
|
22
|
+
projectConfig,
|
|
23
|
+
attributes: { location: { pathname: url.pathname } },
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
:::warning
|
|
28
|
+
Give `serialize()` one client for each request. It does not support two calls at the same
|
|
29
|
+
time on one client.
|
|
30
|
+
:::
|
|
31
|
+
|
|
32
|
+
## 2. Embed the snapshot
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const html = `
|
|
36
|
+
<div id="root">${appHtml}</div>
|
|
37
|
+
<script>window.__PICKED__ = ${JSON.stringify(snapshot)}</script>
|
|
38
|
+
`
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 3. Seed the client and render the slot
|
|
42
|
+
|
|
43
|
+
:::code-group
|
|
44
|
+
|
|
45
|
+
```tsx [React]
|
|
46
|
+
import { PickedProvider, ExperienceSlot } from '@picked/react'
|
|
47
|
+
|
|
48
|
+
export function Page({ snapshot }) {
|
|
49
|
+
return (
|
|
50
|
+
<PickedProvider options={options} snapshot={snapshot}>
|
|
51
|
+
<ExperienceSlot name="page" />
|
|
52
|
+
</PickedProvider>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```svelte [Svelte]
|
|
58
|
+
<script lang="ts">
|
|
59
|
+
import { ExperienceSlot, setPickedContext } from '@picked/svelte'
|
|
60
|
+
|
|
61
|
+
const { snapshot } = $props()
|
|
62
|
+
setPickedContext({ options, snapshot })
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<ExperienceSlot name="page" />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
:::
|
|
69
|
+
|
|
70
|
+
The provider seeds the client at once, so the server HTML and the first paint match.
|
|
71
|
+
|
|
72
|
+
## 4. Point the experience at the slot
|
|
73
|
+
|
|
74
|
+
Set the target selector of your Page experience to `.picked-slot-page`, then publish.
|
|
75
|
+
|
|
76
|
+
## Related
|
|
77
|
+
|
|
78
|
+
- [About server-side rendering](/explanation/why-server-side-rendering) — why the
|
|
79
|
+
snapshot carries condition results.
|
|
80
|
+
- [Server snapshot](/reference/sdk/ssr/serialize) — every parameter.
|
|
81
|
+
- [Your first server-rendered page](/tutorials/first-server-rendered-page).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to set a Content Security Policy
|
|
7
|
+
|
|
8
|
+
This guide shows you how to let the Picked SDK load its resources under a CSP.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
Add the Picked domains to your policy.
|
|
13
|
+
|
|
14
|
+
As an HTTP header:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
Content-Security-Policy: connect-src 'self' https://api.picked.app https://evnts.pckd.dev; img-src 'self' https://img.picked-content.com;
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or as a `<meta>` tag:
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<meta
|
|
24
|
+
http-equiv="Content-Security-Policy"
|
|
25
|
+
content="connect-src 'self' https://api.picked.app https://evnts.pckd.dev; img-src 'self' https://img.picked-content.com;"
|
|
26
|
+
/>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Related
|
|
30
|
+
|
|
31
|
+
- [Content Security Policy](/reference/sdk/content-security-policy) — what each domain is
|
|
32
|
+
for.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to set up MFA
|
|
7
|
+
|
|
8
|
+
This guide shows you how to add an authenticator app to an account, and how to sign in
|
|
9
|
+
with it. Picked supports TOTP authenticator apps only, such as Google Authenticator.
|
|
10
|
+
Every MFA mutation needs authentication.
|
|
11
|
+
|
|
12
|
+
## Who must use MFA
|
|
13
|
+
|
|
14
|
+
Picked staff, and every member of an organization that requires MFA, must sign in with an
|
|
15
|
+
authenticator app. For these users, most operations return the error code `MFA_REQUIRED`
|
|
16
|
+
until the session reaches `AAL2`. The operations that a session at `AAL1` can use are in
|
|
17
|
+
[Authenticator assurance levels](/reference/management-api/authentication#authenticator-assurance-levels).
|
|
18
|
+
The `user.mfa` field tells you where a user stands:
|
|
19
|
+
|
|
20
|
+
```graphql
|
|
21
|
+
query {
|
|
22
|
+
user {
|
|
23
|
+
mfa { required reason enrolled satisfied }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
| Field | Meaning |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| `required` | The user must hold an `AAL2` session to use the fields that need it. |
|
|
31
|
+
| `reason` | `STAFF` or `ORGANIZATION`. Empty when `required` is false. |
|
|
32
|
+
| `enrolled` | The user holds a verified authenticator. |
|
|
33
|
+
| `satisfied` | The session that made the request meets the requirement. |
|
|
34
|
+
|
|
35
|
+
## 1. Add an authenticator
|
|
36
|
+
|
|
37
|
+
```graphql
|
|
38
|
+
mutation {
|
|
39
|
+
mfaFactorEnroll(input: { friendlyName: "Work phone" }) {
|
|
40
|
+
factor { id factorType status }
|
|
41
|
+
totp { qrCode secret uri }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
A new factor has the status `UNVERIFIED`. Show `qrCode` (SVG markup) for the user to scan,
|
|
47
|
+
or `secret` for the user to enter into the app. The API returns it one time only.
|
|
48
|
+
|
|
49
|
+
Before it adds the factor, the mutation deletes the caller's factors that are not verified.
|
|
50
|
+
But it keeps the two newest of these factors if they are less than 60 seconds old. A
|
|
51
|
+
different setup can still use them, for example in a different browser tab. The mutation
|
|
52
|
+
also deletes a factor that is not verified and has the `friendlyName` that you give.
|
|
53
|
+
Therefore, a setup that did not finish does not stop a new setup.
|
|
54
|
+
|
|
55
|
+
## 2. Open a challenge
|
|
56
|
+
|
|
57
|
+
```graphql
|
|
58
|
+
mutation {
|
|
59
|
+
mfaChallengeCreate(input: { factorId: "factor-id" }) {
|
|
60
|
+
challengeId
|
|
61
|
+
expiresAt
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 3. Verify the code
|
|
67
|
+
|
|
68
|
+
```graphql
|
|
69
|
+
mutation {
|
|
70
|
+
mfaChallengeVerify(input: {
|
|
71
|
+
factorId: "factor-id"
|
|
72
|
+
challengeId: "challenge-id"
|
|
73
|
+
code: "123456"
|
|
74
|
+
}) {
|
|
75
|
+
session { accessToken refreshToken aal }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The session moves to `AAL2`, and the factor status changes to `VERIFIED`. Use the returned
|
|
81
|
+
tokens from this point. A wrong code returns `MFA_CHALLENGE_FAILED`.
|
|
82
|
+
|
|
83
|
+
## Sign in with an authenticator
|
|
84
|
+
|
|
85
|
+
After `sessionCreate`, the session is at `AAL1`. When `session.user.mfa.enrolled` is
|
|
86
|
+
`true`, do steps 2 and 3 against one of the user's verified factors. The query
|
|
87
|
+
`user { mfaFactors { id status } }` lists them. When `required` is `true` and `enrolled`
|
|
88
|
+
is `false`, do steps 1 to 3.
|
|
89
|
+
|
|
90
|
+
## Remove an authenticator
|
|
91
|
+
|
|
92
|
+
```graphql
|
|
93
|
+
mutation {
|
|
94
|
+
mfaFactorUnenroll(input: { factorId: "factor-id" }) {
|
|
95
|
+
success
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To remove a verified factor, the session must be at `AAL2`. An `AAL1` session receives
|
|
101
|
+
`MFA_REQUIRED`.
|
|
102
|
+
|
|
103
|
+
A user who must use MFA always keeps at least one authenticator. A request to remove
|
|
104
|
+
their last one fails with `VALIDATION_ERROR`. To replace an authenticator, add the new
|
|
105
|
+
one first, then remove the old one. A user with the `users/reset_mfa` scope clears the
|
|
106
|
+
last one with `userMfaReset`.
|
|
107
|
+
|
|
108
|
+
## API and MCP
|
|
109
|
+
|
|
110
|
+
You can also do this task with the [Management API](/reference/management-api/schema), the [MCP server](/reference/tools/mcp), or code that you send to [`picked_run`](/reference/tools/mcp-run).
|
|
111
|
+
|
|
112
|
+
| Task | GraphQL | MCP tool | Run |
|
|
113
|
+
| --- | --- | --- | --- |
|
|
114
|
+
| Read the MFA status of the user | [`user`](/reference/management-api/schema/auth#user) | None | None |
|
|
115
|
+
| Add an authenticator | [`mfaFactorEnroll`](/reference/management-api/schema/auth#mfafactorenroll) | None | None |
|
|
116
|
+
| Open a challenge | [`mfaChallengeCreate`](/reference/management-api/schema/auth#mfachallengecreate) | None | None |
|
|
117
|
+
| Verify the code | [`mfaChallengeVerify`](/reference/management-api/schema/auth#mfachallengeverify) | None | None |
|
|
118
|
+
| Sign in with an authenticator | [`sessionCreate`](/reference/management-api/schema/auth#sessioncreate), [`mfaChallengeCreate`](/reference/management-api/schema/auth#mfachallengecreate), [`mfaChallengeVerify`](/reference/management-api/schema/auth#mfachallengeverify) | None | None |
|
|
119
|
+
| Remove an authenticator | [`mfaFactorUnenroll`](/reference/management-api/schema/auth#mfafactorunenroll) | None | None |
|
|
120
|
+
|
|
121
|
+
## Related
|
|
122
|
+
|
|
123
|
+
- [Authentication](/reference/management-api/authentication) — every mutation and the
|
|
124
|
+
assurance levels.
|
|
125
|
+
- [Authorization and scopes](/reference/management-api/authorization-and-scopes) — who
|
|
126
|
+
can reset the MFA of another user.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to switch workspaces
|
|
7
|
+
|
|
8
|
+
This guide shows you how to point your local tooling at a different project or workspace.
|
|
9
|
+
Your application then renders that workspace's content and types on your machine. It expects
|
|
10
|
+
a `picked.config.ts` and the [CLI](/reference/tools/cli).
|
|
11
|
+
|
|
12
|
+
Your tooling reads the project and surface named in the committed `picked.config.ts`. The
|
|
13
|
+
CLI writes your choice to `.picked/settings.json` instead. That file is per-developer and
|
|
14
|
+
Git ignores it, so the committed default stays as it is and one command puts it back.
|
|
15
|
+
|
|
16
|
+
See [Workspaces](/reference/dashboard/workspaces) for what Live, Draft, and Archived mean.
|
|
17
|
+
|
|
18
|
+
## 1. Sign in
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
picked login
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This opens your browser for a one-time OAuth sign-in and stores a session under
|
|
25
|
+
`~/.picked/`. Confirm it with `picked whoami`. See
|
|
26
|
+
[CLI authentication](/how-to/authenticate-the-cli).
|
|
27
|
+
|
|
28
|
+
## 2. Find a workspace
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
picked workspace list
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Acme Corp. (acme-corporation)
|
|
36
|
+
Storefront [proj_a1b2]
|
|
37
|
+
Default Storefront [LIVE] (live)
|
|
38
|
+
Checkout rework [DRAFT]
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Note the **project id** (`proj_a1b2`) and the name or the id of the workspace you want.
|
|
42
|
+
|
|
43
|
+
## 3. Switch to the draft
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
picked workspace use --project proj_a1b2 --workspace ws_draft
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Active workspace: Checkout rework [DRAFT] in project proj_a1b2 (source: preview)
|
|
51
|
+
Generated types at /app/src/picked-env.d.ts
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
A command that names **one specific workspace** (draft, live, or archived):
|
|
55
|
+
|
|
56
|
+
- writes the selection (and its [preview token](/reference/delivery-api/preview-caching-crawling)) to
|
|
57
|
+
`.picked/settings.json`,
|
|
58
|
+
- switches the resolved `source` to `preview` for that project, and
|
|
59
|
+
- regenerates `picked-env.d.ts` from that workspace's schema (skip with `--no-generate`).
|
|
60
|
+
|
|
61
|
+
To browse instead, run `picked workspace use` with no flags. The interactive picker lists
|
|
62
|
+
every project, with **Published (live version)** and each of its workspaces.
|
|
63
|
+
|
|
64
|
+
## 4. See the draft in your app
|
|
65
|
+
|
|
66
|
+
Both readers of the selection use `.picked/settings.json` with no change to your
|
|
67
|
+
configuration:
|
|
68
|
+
|
|
69
|
+
- **Type generation** now reads the draft schema. Rerun `picked generate types` after more
|
|
70
|
+
edits.
|
|
71
|
+
- The **[Vite plugin](/reference/tools/vite-plugin)** reads the draft's configuration and
|
|
72
|
+
content in development and in a build. It sends the preview token to the
|
|
73
|
+
[Delivery API](/reference/delivery-api). Restart the dev server to apply a switch.
|
|
74
|
+
|
|
75
|
+
Your application renders the unpublished draft on your machine, with types.
|
|
76
|
+
|
|
77
|
+
## 5. Switch back to live
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
picked workspace use --project proj_a1b2
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
A command that names a project with no `--workspace`, or **Published (live version)** in the
|
|
84
|
+
picker, discards the preview token and returns `source` to `published`. To confirm what is
|
|
85
|
+
active:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
picked status
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Config default: project proj_a1b2 (source: published)
|
|
93
|
+
Active selection: none (using the config default).
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## CI and headless runs
|
|
97
|
+
|
|
98
|
+
`.picked/settings.json` is a local, per-developer file. Do not commit it. To choose one
|
|
99
|
+
workspace in CI with no selection file, set the environment directly:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
PICKED_PROJECT_ID=proj_a1b2 \
|
|
103
|
+
PICKED_PREVIEW_TOKEN="$DRAFT_TOKEN" \
|
|
104
|
+
picked generate types --check
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`PICKED_PREVIEW_TOKEN` applies only when the resolved `source` is `preview`. See the
|
|
108
|
+
[CLI environment variables](/reference/tools/cli#environment-variables) for the full
|
|
109
|
+
precedence order.
|
|
110
|
+
|
|
111
|
+
:::note
|
|
112
|
+
A preview token is a long-lived credential for one workspace. Keep it out of the version
|
|
113
|
+
control system, as you do with each other credential. Git ignores `.picked/settings.json`
|
|
114
|
+
for this reason, because `picked workspace use` writes a token there.
|
|
115
|
+
:::
|
|
116
|
+
|
|
117
|
+
## Related
|
|
118
|
+
|
|
119
|
+
- [CLI](/reference/tools/cli) — every command and flag.
|
|
120
|
+
- [Workspaces](/reference/dashboard/workspaces) — Live, Draft, and Archived states.
|
|
121
|
+
- [Type generation](/reference/sdk/type-generation) — how the schema becomes types.
|
|
122
|
+
- [Preview, cache, and crawlers](/reference/delivery-api/preview-caching-crawling) — preview tokens on the Delivery API.
|