@picked/client 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.
Files changed (147) hide show
  1. package/README.md +34 -158
  2. package/dist/{api-BlRFU0Fi.js → api-BOKA2i46.js} +1 -1
  3. package/dist/{api-AaQeg3Ij.cjs → api-C5jUHF3A.cjs} +1 -1
  4. package/dist/cjs/index.js +2 -2
  5. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  6. package/dist/cjs/server/index.js +1 -1
  7. package/dist/esm/index.js +2 -2
  8. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  9. package/dist/esm/server/index.js +2 -2
  10. package/dist/{plugin-CVD2TnRC.cjs → plugin-BcB9ah7q.cjs} +1 -1
  11. package/dist/{plugin-DhznDG-h.js → plugin-COWxZiTa.js} +2 -2
  12. package/dist/{preview-unavailable-mW4Pj3Ph.js → preview-unavailable-BJjc3UNr.js} +1 -1
  13. package/dist/{preview-unavailable-xWLCr93y.cjs → preview-unavailable-CV1BonKA.cjs} +1 -1
  14. package/dist/{provider-COb_V-yq.js → provider-CszmtTg3.js} +1 -1
  15. package/dist/{provider-zag5m5GH.cjs → provider-daBChM0G.cjs} +1 -1
  16. package/package.json +5 -5
  17. package/dist/docs/_root.css +0 -101
  18. package/dist/docs/explanation/conditions-and-the-logic-engine.md +0 -94
  19. package/dist/docs/explanation/content-references.md +0 -99
  20. package/dist/docs/explanation/feature-flag-allocation.md +0 -218
  21. package/dist/docs/explanation/how-picked-works.md +0 -124
  22. package/dist/docs/explanation/how-pickedql-works.md +0 -76
  23. package/dist/docs/explanation/pages-and-flows.md +0 -64
  24. package/dist/docs/explanation/the-content-model.md +0 -87
  25. package/dist/docs/explanation/the-two-apis.md +0 -68
  26. package/dist/docs/explanation/why-server-side-rendering.md +0 -76
  27. package/dist/docs/explanation/workspaces-and-versions.md +0 -71
  28. package/dist/docs/how-to/add-a-step-field-or-action.md +0 -43
  29. package/dist/docs/how-to/analytics/index.md +0 -316
  30. package/dist/docs/how-to/archive-or-delete-a-workspace.md +0 -46
  31. package/dist/docs/how-to/authenticate-the-cli.md +0 -101
  32. package/dist/docs/how-to/authenticate-with-a-magic-link.md +0 -47
  33. package/dist/docs/how-to/authenticate-with-a-password.md +0 -59
  34. package/dist/docs/how-to/authenticate-with-an-api-key.md +0 -51
  35. package/dist/docs/how-to/authenticate-with-oauth.md +0 -40
  36. package/dist/docs/how-to/build-a-flow.md +0 -93
  37. package/dist/docs/how-to/call-an-external-api-from-a-workflow.md +0 -102
  38. package/dist/docs/how-to/connect-the-mcp-server.md +0 -46
  39. package/dist/docs/how-to/create-a-content-entry.md +0 -48
  40. package/dist/docs/how-to/create-a-project.md +0 -29
  41. package/dist/docs/how-to/create-an-experience.md +0 -42
  42. package/dist/docs/how-to/create-and-revoke-an-api-key.md +0 -42
  43. package/dist/docs/how-to/debug-with-the-chrome-extension.md +0 -57
  44. package/dist/docs/how-to/define-a-page-layout.md +0 -46
  45. package/dist/docs/how-to/fill-and-publish-a-page.md +0 -66
  46. package/dist/docs/how-to/install-the-gtm-template.md +0 -84
  47. package/dist/docs/how-to/install-the-sdk.md +0 -93
  48. package/dist/docs/how-to/install-the-vite-plugin.md +0 -69
  49. package/dist/docs/how-to/invite-and-remove-members.md +0 -35
  50. package/dist/docs/how-to/point-one-entry-at-another.md +0 -61
  51. package/dist/docs/how-to/preview-a-workspace.md +0 -28
  52. package/dist/docs/how-to/publish-a-workspace.md +0 -30
  53. package/dist/docs/how-to/read-a-feature-flag.md +0 -113
  54. package/dist/docs/how-to/read-a-referenced-entry.md +0 -109
  55. package/dist/docs/how-to/register-a-component.md +0 -55
  56. package/dist/docs/how-to/register-an-action-handler.md +0 -85
  57. package/dist/docs/how-to/register-an-api-that-uses-oauth2.md +0 -107
  58. package/dist/docs/how-to/render-a-step-form.md +0 -131
  59. package/dist/docs/how-to/render-an-unpublished-preview.md +0 -41
  60. package/dist/docs/how-to/retry-a-failed-call-with-a-loop.md +0 -81
  61. package/dist/docs/how-to/reuse-a-section.md +0 -53
  62. package/dist/docs/how-to/reuse-a-step-field-or-action.md +0 -28
  63. package/dist/docs/how-to/roll-back-a-published-version.md +0 -26
  64. package/dist/docs/how-to/run-an-ab-test.md +0 -49
  65. package/dist/docs/how-to/run-code-on-a-form-submission.md +0 -125
  66. package/dist/docs/how-to/server-render-a-page.md +0 -81
  67. package/dist/docs/how-to/set-a-content-security-policy.md +0 -32
  68. package/dist/docs/how-to/set-up-mfa.md +0 -113
  69. package/dist/docs/how-to/switch-workspaces.md +0 -122
  70. package/dist/docs/how-to/upload-and-use-an-asset.mdx +0 -73
  71. package/dist/docs/how-to/validate-a-field.md +0 -52
  72. package/dist/docs/how-to/wait-for-an-action-response.md +0 -182
  73. package/dist/docs/how-to/write-a-condition.md +0 -45
  74. package/dist/docs/how-to/write-a-predicate.md +0 -60
  75. package/dist/docs/index.md +0 -59
  76. package/dist/docs/reference/dashboard/actions.mdx +0 -56
  77. package/dist/docs/reference/dashboard/api-keys.mdx +0 -38
  78. package/dist/docs/reference/dashboard/conditions.mdx +0 -42
  79. package/dist/docs/reference/dashboard/content/asset-library.mdx +0 -63
  80. package/dist/docs/reference/dashboard/content/blocks.mdx +0 -57
  81. package/dist/docs/reference/dashboard/content/content-entries.mdx +0 -95
  82. package/dist/docs/reference/dashboard/content/models.mdx +0 -108
  83. package/dist/docs/reference/dashboard/content/pages.mdx +0 -61
  84. package/dist/docs/reference/dashboard/experiences.mdx +0 -51
  85. package/dist/docs/reference/dashboard/external-apis.md +0 -169
  86. package/dist/docs/reference/dashboard/features.mdx +0 -154
  87. package/dist/docs/reference/dashboard/fields.mdx +0 -106
  88. package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +0 -58
  89. package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +0 -57
  90. package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +0 -72
  91. package/dist/docs/reference/dashboard/flow-builder/nodes.md +0 -63
  92. package/dist/docs/reference/dashboard/labels.md +0 -321
  93. package/dist/docs/reference/dashboard/lead-search.md +0 -224
  94. package/dist/docs/reference/dashboard/projects.mdx +0 -44
  95. package/dist/docs/reference/dashboard/reports.mdx +0 -43
  96. package/dist/docs/reference/dashboard/steps.mdx +0 -37
  97. package/dist/docs/reference/dashboard/team-management.md +0 -29
  98. package/dist/docs/reference/dashboard/workflow-runs.md +0 -142
  99. package/dist/docs/reference/dashboard/workflow-templates.md +0 -182
  100. package/dist/docs/reference/dashboard/workflow-test-runs.md +0 -77
  101. package/dist/docs/reference/dashboard/workspace-versioning.mdx +0 -30
  102. package/dist/docs/reference/dashboard/workspaces.mdx +0 -76
  103. package/dist/docs/reference/delivery-api/experience-content.md +0 -152
  104. package/dist/docs/reference/delivery-api/index.md +0 -45
  105. package/dist/docs/reference/delivery-api/preview-caching-crawling.md +0 -79
  106. package/dist/docs/reference/delivery-api/project-config.md +0 -65
  107. package/dist/docs/reference/delivery-api/workspace-schema.md +0 -107
  108. package/dist/docs/reference/glossary.md +0 -201
  109. package/dist/docs/reference/management-api/authentication.md +0 -87
  110. package/dist/docs/reference/management-api/authorization-and-scopes.md +0 -291
  111. package/dist/docs/reference/management-api/error-handling.md +0 -232
  112. package/dist/docs/reference/management-api/pagination.md +0 -192
  113. package/dist/docs/reference/pickedql/data-sources.md +0 -174
  114. package/dist/docs/reference/pickedql/dimensions.md +0 -103
  115. package/dist/docs/reference/pickedql/filtering.md +0 -64
  116. package/dist/docs/reference/pickedql/index.md +0 -18
  117. package/dist/docs/reference/pickedql/schema.md +0 -172
  118. package/dist/docs/reference/pickedql/virtual-functions.md +0 -248
  119. package/dist/docs/reference/sdk/actions.md +0 -154
  120. package/dist/docs/reference/sdk/analytics-events.md +0 -453
  121. package/dist/docs/reference/sdk/conditions.md +0 -147
  122. package/dist/docs/reference/sdk/content-security-policy.md +0 -21
  123. package/dist/docs/reference/sdk/content.md +0 -253
  124. package/dist/docs/reference/sdk/experiences.md +0 -51
  125. package/dist/docs/reference/sdk/features.md +0 -256
  126. package/dist/docs/reference/sdk/fields.md +0 -255
  127. package/dist/docs/reference/sdk/index.md +0 -68
  128. package/dist/docs/reference/sdk/plugins/create-experience.md +0 -123
  129. package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +0 -74
  130. package/dist/docs/reference/sdk/plugins/index.md +0 -29
  131. package/dist/docs/reference/sdk/plugins/window-object.md +0 -25
  132. package/dist/docs/reference/sdk/predicates.md +0 -43
  133. package/dist/docs/reference/sdk/ssr/index.md +0 -33
  134. package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +0 -103
  135. package/dist/docs/reference/sdk/ssr/serialize.md +0 -80
  136. package/dist/docs/reference/sdk/ssr/slots-and-placements.md +0 -113
  137. package/dist/docs/reference/sdk/steps.md +0 -86
  138. package/dist/docs/reference/sdk/type-generation.md +0 -265
  139. package/dist/docs/reference/tools/chrome-extension.md +0 -16
  140. package/dist/docs/reference/tools/cli.md +0 -292
  141. package/dist/docs/reference/tools/image-optimisation-service.md +0 -104
  142. package/dist/docs/reference/tools/mcp.md +0 -136
  143. package/dist/docs/reference/tools/vite-plugin.md +0 -163
  144. package/dist/docs/tutorials/first-api-call.md +0 -235
  145. package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +0 -143
  146. package/dist/docs/tutorials/first-experience.mdx +0 -254
  147. package/dist/docs/tutorials/first-server-rendered-page.mdx +0 -186
@@ -1,107 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to register an API that uses OAuth2
7
-
8
- This guide shows you how to let a workflow call an API whose access tokens expire, such as
9
- Zoho CRM. You need a client ID and a client secret from the provider. For the refresh token
10
- grant, you also need a refresh token.
11
-
12
- Picked keeps the credential, gets an access token from the provider, and sends the token
13
- with each request. Picked gets a new token before the old token expires.
14
-
15
- ## 1. Make a refresh token in Zoho
16
-
17
- Do this step for Zoho CRM only. For another provider, get the credential from the
18
- provider's documentation.
19
-
20
- 1. Open the Zoho API console for the region of your Zoho account.
21
- 2. Add a client of the type `Self Client`.
22
- 3. Make a grant code with the scopes that the workflow needs, such as
23
- `ZohoCRM.modules.leads.CREATE`.
24
- 4. Send a `POST` request to the token URL of your region, such as
25
- `https://accounts.zoho.com.au/oauth/v2/token`. Put the parameters in the form body, not
26
- in the URL. The parameters are `grant_type=authorization_code`, `client_id`,
27
- `client_secret`, and `code` with the grant code. The grant code expires soon, so do this
28
- step immediately.
29
- 5. Keep the `refresh_token` from the answer.
30
-
31
- :::warning
32
- Make the refresh token as a Zoho user that only Picked uses. Zoho keeps 20 refresh tokens
33
- for each user and client. When you make one more, Zoho stops the oldest refresh token. That
34
- token can be the token that Picked uses.
35
- :::
36
-
37
- ## 2. Register the external API
38
-
39
- 1. Open **Integrations**.
40
- 2. Choose **Configure external APIs**.
41
- 3. Choose **New external API**.
42
- 4. For Zoho CRM, set **Preset** to the region of your Zoho account. The preset sets the
43
- **Display name**, the **Origin**, the **Credential** and the settings of the OAuth2
44
- credential. Then go to step 10. If **Preset** does not show your region, do steps 5 to 9.
45
- 5. Enter a **Display name**.
46
- 6. Enter the **Origin**, such as `https://www.zohoapis.com.au`.
47
- 7. Set **Credential** to **OAuth2 credential**.
48
- 8. Enter the **Token URL** from the provider's documentation. Do not put a secret in the
49
- token URL.
50
- 9. Set the **Grant**, the **Client authentication** and the **Header scheme** from the
51
- provider's documentation.
52
- 10. Enter the **Client ID**.
53
- 11. Enter the **Client secret**.
54
- 12. For the refresh token grant, enter the **Refresh token**.
55
- 13. Choose **Register external API**.
56
-
57
- The client secret and the refresh token are write-only. After you save them, Picked shows
58
- only that they are stored.
59
-
60
- ## 3. Add a credential to an external API that you registered
61
-
62
- 1. Open the external API.
63
- 2. Choose **Use an OAuth2 credential**.
64
- 3. For Zoho CRM, set **Preset** to the region of your Zoho account. For another provider,
65
- do steps 8 and 9 of section 2.
66
- 4. Do steps 10 to 12 of section 2.
67
- 5. Choose **Save credential**.
68
-
69
- The credential replaces the authorization header of the external API.
70
-
71
- ## 4. Refresh only for an expired token
72
-
73
- Some APIs answer 401 for an error that a new token does not correct. To get a new token only
74
- for an expired token:
75
-
76
- 1. Open the external API.
77
- 2. Choose **Edit OAuth2 credential**.
78
- 3. In **401 rule: response body path**, enter the path of the error code in the 401 answer,
79
- such as `code`. Put a dot between the parts of the path, for example `data.0.code`.
80
- 4. In **401 rule: values**, enter the error codes that show an expired token, such as
81
- `INVALID_TOKEN`.
82
- 5. Choose **Save credential**.
83
-
84
- The Zoho CRM preset sets this rule for you.
85
-
86
- ## 5. Replace a refresh token that the provider rejected
87
-
88
- When the provider rejects the credential, the external API page shows the reason in **Last
89
- refresh failure**. Each call fails with `credential_rejected` until you correct the
90
- credential.
91
-
92
- 1. Make a new refresh token.
93
- 2. Open the external API.
94
- 3. Choose **Edit OAuth2 credential**.
95
- 4. Enter the new **Refresh token**.
96
- 5. Choose **Save credential**.
97
-
98
- Leave the **Client secret** empty to keep the stored client secret. If you change the
99
- **Token URL**, the **Client ID** or the **Client authentication**, enter the client secret
100
- and the refresh token again.
101
-
102
- ## Related
103
-
104
- - [External APIs](/reference/dashboard/external-apis#oauth2-credential) — every setting of
105
- an OAuth2 credential, and when Picked gets a new token.
106
- - [How to call an external API from a workflow](/how-to/call-an-external-api-from-a-workflow)
107
- — the node that sends the request.
@@ -1,131 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to render a step form
7
-
8
- This guide shows you how to render the fields of the active step and let a visitor submit
9
- them.
10
-
11
- ## 1. Put the steps in a router
12
-
13
- `StepRouter` watches the step state and activates the `Step` whose `id` matches.
14
-
15
- :::code-group
16
-
17
- ```tsx [React]
18
- import { StepRouter, Step } from '@picked/react/router'
19
-
20
- function MyExperience() {
21
- return (
22
- <StepRouter>
23
- <Step id="welcome">
24
- <WelcomeScreen />
25
- </Step>
26
- <Step id="contact">
27
- <ContactForm />
28
- </Step>
29
- </StepRouter>
30
- )
31
- }
32
- ```
33
-
34
- ```svelte [Svelte]
35
- <script lang="ts">
36
- import { StepRouter, Step } from '@picked/svelte/router'
37
- </script>
38
-
39
- <StepRouter>
40
- <Step id="welcome">
41
- <WelcomeScreen />
42
- </Step>
43
- <Step id="contact">
44
- <ContactForm />
45
- </Step>
46
- </StepRouter>
47
- ```
48
-
49
- :::
50
-
51
- :::note
52
- A router must hold every Step, even when there is only one Step.
53
- :::
54
-
55
- ## 2. Render the fields
56
-
57
- Bind `form.props` to your `<form>` element and map over the fields.
58
-
59
- :::code-group
60
-
61
- ```tsx [React]
62
- import { useStep, useStoreGlobal } from '@picked/react/hooks'
63
-
64
- function StepForm() {
65
- const { fields, form } = useStep()
66
- const currentFields = useStoreGlobal(fields)
67
- const isSubmitting = useStoreGlobal(form.submitting)
68
-
69
- return (
70
- <form {...form.props}>
71
- {currentFields.map((field) => (
72
- <div key={field.id}>
73
- <label htmlFor={field.id}>{field.label}</label>
74
- <input
75
- id={field.id}
76
- name={field.id}
77
- value={field.value ?? ''}
78
- onChange={field.onChange}
79
- onBlur={field.onBlur}
80
- />
81
- {field.error && field.touched && <p className="error">{field.error.userMessage}</p>}
82
- </div>
83
- ))}
84
- <button type="submit" disabled={isSubmitting}>Continue</button>
85
- </form>
86
- )
87
- }
88
- ```
89
-
90
- ```svelte [Svelte]
91
- <script lang="ts">
92
- import { getStep } from '@picked/svelte/hooks'
93
-
94
- const { fields, form } = getStep()
95
- const isSubmitting = form.submitting
96
- </script>
97
-
98
- <form {...form.props}>
99
- {#each $fields as field}
100
- <div>
101
- <label for={field.id}>{field.label}</label>
102
- <input
103
- id={field.id}
104
- name={field.id}
105
- value={field.value ?? ''}
106
- onchange={field.onChange}
107
- onblur={field.onBlur}
108
- />
109
- {#if field.error && field.touched}
110
- <p class="error">{field.error.userMessage}</p>
111
- {/if}
112
- </div>
113
- {/each}
114
- <button type="submit" disabled={$isSubmitting}>Continue</button>
115
- </form>
116
- ```
117
-
118
- :::
119
-
120
- The SDK checks a field on blur, and not while the visitor types.
121
-
122
- ## 3. Load a large step lazily
123
-
124
- Pass a dynamic import to the `component` prop of `<Step>`. The SDK does not load the
125
- content until that step becomes active.
126
-
127
- ## Related
128
-
129
- - [How to run code on a form submission](/how-to/run-code-on-a-form-submission) — the
130
- callbacks.
131
- - [SDK steps](/reference/sdk/steps) — the `StepContext` shape.
@@ -1,41 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to render an unpublished preview
7
-
8
- This guide shows you how to render draft content on your server. Your server cannot read
9
- the query string of the browser, so you must pass the token yourself.
10
-
11
- ## 1. Get the token
12
-
13
- The management API holds the preview token of a workspace in the `previewToken` field. The
14
- preview action in the dashboard also makes one for you.
15
-
16
- ## 2. Read the config with the token
17
-
18
- ```bash
19
- curl "https://api.picked.app/api/v1/projects/proj_123?preview_token=<token>"
20
- ```
21
-
22
- A preview response returns `versionId: null`. An invalid token returns `401`.
23
-
24
- ## 3. Pass the same token to `serialize()`
25
-
26
- ```ts
27
- const snapshot = await serialize(client, {
28
- projectConfig,
29
- attributes: { location: { pathname: '/promo' } },
30
- previewToken,
31
- })
32
- ```
33
-
34
- Use the same token for both requests. The configuration and the content then come from the same
35
- preview.
36
-
37
- ## Related
38
-
39
- - [About the two APIs](/explanation/the-two-apis) — how a preview stays out of the search
40
- index.
41
- - [Preview, cache, and crawlers](/reference/delivery-api/preview-caching-crawling).
@@ -1,81 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to retry a failed call with a loop
7
-
8
- This guide shows you how to make a workflow send a request again after the request fails.
9
- The workflow waits before each new try. It stops after a number of tries that you set.
10
-
11
- You need a workflow with an **External API** node first. Refer to
12
- [How to call an external API from a workflow](/how-to/call-an-external-api-from-a-workflow).
13
-
14
- ## The loop
15
-
16
- A loop is a path of edges that goes back to a node that the run reached before. This loop
17
- has three nodes:
18
-
19
- | Node | Function |
20
- | ------------------- | ------------------------------------------------ |
21
- | External API `send` | Sends the request. |
22
- | Condition `check` | Decides if the workflow sends the request again. |
23
- | Sleep `pause` | Waits before the next try. |
24
-
25
- When you save a workflow, Picked refuses a loop that does not have a sleep node and a
26
- condition node on it. Picked also refuses an edge from a node to the same node.
27
-
28
- ## 1. Connect the error exit to a condition
29
-
30
- 1. Open the workflow.
31
- 2. Choose **Add condition** on the error exit of `send`.
32
- 3. In the rule of `check`, test `{{ nodes.send.error.retryable }}`.
33
- 4. Connect the `false` exit of `check` to the nodes that record the failure.
34
-
35
- `check` runs only when the call fails. The rule can then read the error of the last try.
36
-
37
- ## 2. Add the sleep node
38
-
39
- 1. Choose **Add sleep** on the `true` exit of `check`.
40
- 2. Set **Wait for** to the time between two tries.
41
- 3. Connect the exit of `pause` to the input of `send`.
42
-
43
- The editor shows a loop as an edge that goes back to `send`.
44
-
45
- ## 3. Set the number of tries
46
-
47
- Each node in the loop runs one time for each try. A run can visit one node a maximum
48
- number of times. This number is the visit cap of the workflow.
49
-
50
- 1. Open the workflow settings.
51
- 2. Set **Visit cap** to a number from 1 to 100. If you do not set it, the visit cap is 10.
52
-
53
- A node can get to the visit cap. If the run then gets to the node again, the run stops.
54
- The run shows `Failed` with the code `loop_limit_reached`.
55
-
56
- To stop the loop before the visit cap, test `current.visit` in the rule of `check`.
57
- Its value is the number of the visit to `check`. This is also the number of failed tries.
58
- This rule tries a maximum of 3 times:
59
-
60
- ```json
61
- {
62
- "and": [{ "var": "nodes.send.error.retryable" }, { "<": ["{{ current.visit }}", 3] }]
63
- }
64
- ```
65
-
66
- With this rule, the run continues on the `false` exit of `check` after 3 failures.
67
-
68
- ## 4. Read the result
69
-
70
- A node reads the last visit of another node. After the loop, `{{ nodes.send.status }}`
71
- gives the status of the last try.
72
-
73
- The **Tasks** card of the run shows each visit as a task. Refer to the
74
- [Workflow runs reference](/reference/dashboard/workflow-runs#tasks).
75
-
76
- ## Related
77
-
78
- - [Workflow runs](/reference/dashboard/workflow-runs) — the tasks of each visit, and the
79
- visit cap.
80
- - [Workflow templates](/reference/dashboard/workflow-templates) — the data that a node
81
- reads in a loop.
@@ -1,53 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to reuse a section
7
-
8
- This guide shows you how to define a common structure one time and use it in more than
9
- one Model.
10
-
11
- ## 1. Create the section
12
-
13
- 1. Click **Pages** in the sidebar.
14
- 2. Click **Page Sections**.
15
- 3. Click **New block**.
16
- 4. Enter a **Name** and a **Key**.
17
- 5. Add your fields.
18
- 6. Click **Create block**.
19
-
20
- The **Category** is **Section** already, because you opened the list from **Page
21
- Sections**.
22
-
23
- ## 2. Accept the section in a Model
24
-
25
- 1. Open a page layout or a step layout.
26
- 2. Add a **Page Sections** field to the schema.
27
- 3. Click **Save**.
28
-
29
- The field now accepts any Block of the Section category. Make the field repeatable to
30
- build a page from a list of sections.
31
-
32
- If you want one section at a fixed place instead of a list, add a **Content block** field.
33
- Set its **Block category** to the **Section** category.
34
-
35
- ## 3. Choose the section in an entry
36
-
37
- 1. Open a content entry that uses the Model.
38
- 2. Find the field that you added.
39
- 3. Choose your Block.
40
- 4. Fill in the fields of the Block.
41
- 5. Click **Save**.
42
-
43
- :::warning
44
- An edit to a Block does not migrate the entries that use it. Check each affected content
45
- entry again, and correct every field error before you publish.
46
- :::
47
-
48
- ## Related
49
-
50
- - [About the content model](/explanation/the-content-model) — why a schema change does not
51
- migrate your data.
52
- - [Blocks](/reference/dashboard/content/blocks) — the reference.
53
- - [Models](/reference/dashboard/content/models) — every field type.
@@ -1,28 +0,0 @@
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
- ## Related
25
-
26
- - [Steps](/reference/dashboard/steps) — the step options.
27
- - [Fields](/reference/dashboard/fields) — the field options.
28
- - [Actions](/reference/dashboard/actions) — the action options.
@@ -1,26 +0,0 @@
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
- ## Related
23
-
24
- - [About workspaces and versions](/explanation/workspaces-and-versions) — why a roll-back
25
- changes no data.
26
- - [Publish history](/reference/dashboard/workspace-versioning) — the version list.
@@ -1,49 +0,0 @@
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
- ## Related
46
-
47
- - [About feature flag allocation](/explanation/feature-flag-allocation) — why two feature
48
- flags at the same weight give four groups, not two.
49
- - [Feature flags](/reference/dashboard/features) — the controls.
@@ -1,125 +0,0 @@
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.