@picked/client 0.0.101-next.2 → 0.0.101-next.3

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-AaQeg3Ij.cjs → api-9o_emCM5.cjs} +1 -1
  3. package/dist/{api-BlRFU0Fi.js → api-BbQt8aW3.js} +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-I8_6ncy_.cjs} +1 -1
  11. package/dist/{plugin-DhznDG-h.js → plugin-uZJ45vK6.js} +2 -2
  12. package/dist/{preview-unavailable-xWLCr93y.cjs → preview-unavailable-BUNxTYLe.cjs} +1 -1
  13. package/dist/{preview-unavailable-mW4Pj3Ph.js → preview-unavailable-BYFD2a58.js} +1 -1
  14. package/dist/{provider-zag5m5GH.cjs → provider-Bzi_Kb-n.cjs} +1 -1
  15. package/dist/{provider-COb_V-yq.js → provider-CQKp0iUJ.js} +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,76 +0,0 @@
1
- ---
2
- type: explanation
3
- layout: docs
4
- ---
5
-
6
- # About PickedQL
7
-
8
- PickedQL is SQL over your Picked analytics data, but it is not only SQL. It expands what
9
- you write before it runs. Why add a layer at all, and not give you the tables?
10
-
11
- ## The problem it answers
12
-
13
- An A/B test question is short to ask, and the SQL behind it is not. Take one question:
14
- "How many users are in the control group?" It needs four things. It needs a filter on the
15
- variant, a count of distinct users, a join to each dimension in the group, and a tenant
16
- filter.
17
-
18
- Write that by hand for every question, and most of each query is the same text again.
19
-
20
- PickedQL lets you write the short version:
21
-
22
- ```sql
23
- SELECT control_users(), variant_users()
24
- FROM metrics
25
- WHERE project_id = 'your-project-id'
26
- ```
27
-
28
- ## What it expands
29
-
30
- **Virtual tables.** A name such as `metrics` maps to the real tables below it. You name
31
- the thing that you ask about, and not the storage.
32
-
33
- **Virtual functions.** `control_users()` expands to a full aggregate expression. The
34
- definition lives in one place, so every report that counts control users counts them the
35
- same way.
36
-
37
- **Automatic joins.** Point at a dimension column such as `device_category` or
38
- `country_code` and PickedQL adds the `LEFT JOIN` for you. This gives you the most: a
39
- dimension that you did not join is the most common reason for a wrong answer that looks
40
- correct.
41
-
42
- **SQL passthrough.** Standard SQL still works next to a virtual function, and that
43
- includes `CASE WHEN`, window functions, and subqueries. The layer adds; it does not
44
- restrict.
45
-
46
- ## Why every query must carry a tenant filter
47
-
48
- Every query must carry a tenant filter in its `WHERE` clause. That filter is `project_id`
49
- for most tables. The `projects` table uses `id` instead, because there the row ID *is* the
50
- project ID.
51
-
52
- PickedQL reads that filter and checks your permission for that project. The filter is
53
- therefore not a convention that you can forget. Without one, the query does not run.
54
- The isolation is a property of the language, and not of each author.
55
-
56
- ## Which table to reach for
57
-
58
- | Table | Use it for |
59
- | --- | --- |
60
- | `metrics` | A dashboard. The data is aggregated first, so it is much faster than raw events. |
61
- | `events` | Anything deeper. Raw events let you build any breakdown or funnel. |
62
- | `experience_journey` | A sankey or a funnel chart. One line of SQL returns `source, target, users`. |
63
-
64
- Note what `experience_journey` does for you. It builds the eight common table expressions
65
- that a path analysis needs. Those remove the duplicates, rank the top paths, and call
66
- `lagInFrame`. You pass your parameters in the `WHERE` clause.
67
-
68
- Some reference columns are free on `events`. `step_title`, `experience_title`, and
69
- `project_name` come from reference tables that PickedQL joins for you.
70
-
71
- ## Related
72
-
73
- - [PickedQL](/reference/pickedql) — the language surface.
74
- - [Data sources](/reference/pickedql/data-sources) — every table.
75
- - [Virtual functions](/reference/pickedql/virtual-functions) — every function.
76
- - [How to run an analytics query](/how-to/analytics) — worked examples.
@@ -1,64 +0,0 @@
1
- ---
2
- type: explanation
3
- layout: docs
4
- ---
5
-
6
- # About pages and flows
7
-
8
- An experience has two kinds, and the dashboard makes you choose
9
- between them when you create one. Why two, and how do you know which one a piece of work needs?
10
-
11
- ## The two kinds
12
-
13
- | | Page | Flow |
14
- | --- | --- | --- |
15
- | What it is | A standalone experience that your server renders from a content entry. | An interactive experience of more than one step, which the browser renders. |
16
- | Use it for | A landing page or a campaign page where the search rank matters. | A quiz, a survey, a product finder, onboarding of more than one step. |
17
-
18
- The split is not about how complex the content is. It is about **who has to read it**.
19
-
20
- ## Why the split exists
21
-
22
- A crawler and a social preview read the HTML your server returns. Neither waits for
23
- JavaScript in the browser. Content that a search engine must find is therefore
24
- content that must be in the first response. Only a server render puts it there.
25
-
26
- A flow has the reverse constraint. Its value is in the interaction: a visitor answers,
27
- the flow branches, the next screen depends on what came before. None of that can be in the
28
- first response, because none of it exists until the visitor acts.
29
-
30
- Choose a Page when the content must reach a search engine. Choose a Flow when the value is
31
- in the interaction and a browser render is acceptable.
32
-
33
- ## What backs a page
34
-
35
- Four pieces sit behind every Page, and they are separate on purpose:
36
-
37
- 1. A **page layout** sets the shape: which fields the page can hold.
38
- 2. A **content entry** fills that shape with real data.
39
- 3. A **Page** binds one entry, so the SDK can render it.
40
- 4. The **SDK** reads the entry and renders it on your server.
41
-
42
- Layout and entry are separate because one layout backs many entries. Describe a campaign
43
- page one time, then make many pages from it. Change the layout and you must check every
44
- entry again. That is why the dashboard reports an invalid entry and does not serve it.
45
-
46
- A step layout does the same thing for one step inside a flow. The parts behave the same
47
- way. Only the thing that they give shape to is different.
48
-
49
- ## They meet at the same publish
50
-
51
- Both kinds are experiences. Both live in a workspace, both go into the same immutable
52
- version, and both come out of the same Delivery API. The SDK decides where to render each
53
- one, and every step before that treats them the same way.
54
-
55
- This matters, because it means a project mixes them freely. A server-rendered
56
- landing page can carry a browser-rendered quiz inside it.
57
-
58
- ## Related
59
-
60
- - [About how Picked works](/explanation/how-picked-works) — the path that both kinds take.
61
- - [About server-side rendering](/explanation/why-server-side-rendering) — how a Page
62
- reaches the browser.
63
- - [Pages](/reference/dashboard/content/pages) — the page editor.
64
- - [Experiences](/reference/dashboard/experiences) — the flow options.
@@ -1,87 +0,0 @@
1
- ---
2
- type: explanation
3
- layout: docs
4
- ---
5
-
6
- # About the content model
7
-
8
- Picked splits your content into three pieces: a Model, a Block, and a content entry.
9
- Why three, when a page editor needs only one?
10
-
11
- ## Schema and data are separate
12
-
13
- A **Model** is a schema. It sets which fields a piece of content can hold, and it holds
14
- no data itself. A **content entry** is one instance of that schema, filled with real
15
- values.
16
-
17
- One Model backs many entries. Describe a campaign page one time, then make many pages
18
- from it. Each entry carries its own title, its own body, and its own image, but they all
19
- share the shape.
20
-
21
- That split is also what lets your code depend on content that it never saw. Your component
22
- reads `content.title` because the Model promises a `title`. It works for every entry that
23
- comes from that Model.
24
-
25
- ## A category gives a Model a role
26
-
27
- A Model can carry a **category**, and the category decides what the Model gives its shape
28
- to. A **page layout** backs a standalone Page. A **step layout** backs one Step inside a
29
- Flow.
30
-
31
- The category is fixed because it decides where the SDK renders the entry. That is not a
32
- property that you can change under an entry that exists already.
33
-
34
- A Model can also carry no category. Such a Model has no layout role, and nothing renders
35
- its entries directly. It holds the content that other content points at, such as a
36
- product or a category of your own. See
37
- [About content references](/explanation/content-references).
38
-
39
- The three roles are one machine. A layout is a Model with a job in the render path. A
40
- Model with no category is the same machine with no such job.
41
-
42
- ## A Block is a schema fragment
43
-
44
- A Model gives shape to a whole page or a whole step. A **Block** is a part that you put
45
- inside one or more Models.
46
-
47
- Define a hero one time as a Block, then point at it from every Model that needs one.
48
- Change the Block and every Model that holds it changes with it.
49
-
50
- This is the reason Blocks exist at all. Without them you must describe a common
51
- structure again in each Model, and the copies then become different. It is the same
52
- argument for one fact in one place that runs through the rest of this documentation.
53
-
54
- A Block sits **inside** the entry that embeds it. It has no entry of its own, and no id
55
- that you can point at.
56
-
57
- That is the difference between a Block and a reference. A Block is a shape that many
58
- entries hold. A reference is a pointer at one entry that many entries share.
59
-
60
- ## Why a schema change does not migrate your data
61
-
62
- Change a Model or a Block, and Picked does not rewrite the entries behind it. An entry
63
- that no longer matches its schema becomes invalid, and the dashboard shows an error on
64
- each field that does not fit.
65
-
66
- That is deliberate. An automatic change must decide what a new required field holds for
67
- every entry that came before it. Any value that it chooses is content that nobody wrote.
68
- Picked reports the error instead, and you correct it.
69
-
70
- The cost is real. After a schema change, check every entry that uses that Model and fix
71
- each error before you publish. Picked serves valid content only, so an entry with an error
72
- does not reach a visitor.
73
-
74
- ## An error points at the exact field
75
-
76
- A validation error carries a path in JSON style, such as `sections[0].data.title`. The
77
- path holds through nested groups, repeated fields, and Blocks. An error inside a
78
- repeated group therefore tells you which item in that group holds it.
79
-
80
- ## Related
81
-
82
- - [Models](/reference/dashboard/content/models) — every field type.
83
- - [Blocks](/reference/dashboard/content/blocks) — the reusable fragments.
84
- - [Content entries](/reference/dashboard/content/content-entries) — the editor and the
85
- validation.
86
- - [About content references](/explanation/content-references) — how one entry points at another.
87
- - [About pages and flows](/explanation/pages-and-flows) — which category you need.
@@ -1,68 +0,0 @@
1
- ---
2
- type: explanation
3
- layout: docs
4
- ---
5
-
6
- # About the two APIs
7
-
8
- Picked has two HTTP APIs, and a new reader often reaches for the wrong one. This page
9
- covers which is which and why they are separate.
10
-
11
- ## The split
12
-
13
- | | Delivery API | Management API |
14
- | --- | --- | --- |
15
- | Style | REST | GraphQL |
16
- | Access | Public, anonymous | Authenticated |
17
- | Operations | Read-only | Read and write |
18
- | Base | `https://api.picked.app/api/v1` | `POST https://api.picked.app/api/graphql` |
19
- | Use it to | Serve published configuration and content to your application | Control your projects, experiences, and content |
20
-
21
- The short rule is this: **the Delivery API serves your visitors, and the management API
22
- serves you.**
23
-
24
- ## Why they are not one API
25
-
26
- Three properties of the delivery path make it a different kind of API.
27
-
28
- **It is anonymous.** A crawler must read your published page content with no credential at
29
- all. An API that requires a token cannot serve a search engine, and an API that serves a
30
- search engine cannot require one.
31
-
32
- **It is cacheable.** A published response is the same for every reader, so a shared cache
33
- can hold it. The Delivery API sends `s-maxage` for an SDK request, and it sends
34
- `Vary: Picked-Client`. A GraphQL endpoint that takes any query over a `POST` has none of
35
- those properties.
36
-
37
- **It is read-only.** Nothing that a reader reaches without a credential can change your
38
- data. Every write stays on a separate authenticated surface, so that property holds by
39
- design.
40
-
41
- ## What the Delivery API serves
42
-
43
- Two endpoints, and the SDK calls both:
44
-
45
- - **Project config** returns the published configuration of a project: its experiences and
46
- steps, and the content link on each step.
47
- - **Experience content** returns the content entries behind an experience.
48
-
49
- Your server usually calls the first and lets `serialize()` call the second. See
50
- [About server-side rendering](/explanation/why-server-side-rendering).
51
-
52
- ## How a preview stays out of the search index
53
-
54
- A preview needs unpublished content, and by the definition of it that content is not
55
- public. The Delivery API takes a `preview_token` query parameter for exactly that. It then
56
- treats the result differently. `versionId` comes back `null`, the response is `no-store`,
57
- and `robots.txt` does not allow the preview path.
58
-
59
- That last part matters more than it looks. A draft that anybody can read over an anonymous
60
- URL is a draft that a search engine can find. A campaign page that is only part complete
61
- can then appear in the search results of a customer.
62
-
63
- ## Related
64
-
65
- - [Delivery API](/reference/delivery-api) — the endpoints and their responses.
66
- - [Management API](/reference/management-api/authentication) — authentication and scopes.
67
- - [Preview, cache, and crawlers](/reference/delivery-api/preview-caching-crawling) — the
68
- exact cache rules and `robots.txt` rules.
@@ -1,76 +0,0 @@
1
- ---
2
- type: explanation
3
- layout: docs
4
- ---
5
-
6
- # About server-side rendering
7
-
8
- Why does a Page need a snapshot, when the SDK can fetch its content in the browser?
9
- Because the reader that matters most does not run JavaScript.
10
-
11
- ## The constraint
12
-
13
- A crawler and a social preview read the HTML your server returns, and they do not wait for
14
- the browser to fetch anything. If the content of a Page arrives after the first response,
15
- those readers never see it.
16
-
17
- So the content has to be in the HTML. That means your server has to know, before it
18
- answers, which experiences match this URL and what their content is.
19
-
20
- ## What the snapshot is for
21
-
22
- `serialize()` answers that question on the server. It registers your project configuration and
23
- evaluates each experience condition against the URL. It then reads the content for each
24
- experience that matches, and returns a `PickedSnapshot` as plain JSON.
25
-
26
- ```
27
- projectConfig (Delivery API)
28
- -> serialize(client, params) on the server -> PickedSnapshot
29
- -> embed snapshot in HTML
30
- -> client seeds from snapshot -> renders the same markup -> hydrates
31
- ```
32
-
33
- The snapshot carries the exact options the server chose with, and the condition results it
34
- reached. The first render in the browser therefore reuses the decisions of the server. It
35
- does not evaluate them a second time.
36
-
37
- That last point is the whole reason the snapshot holds condition results and not only
38
- content. A browser that evaluates the conditions itself can reach a different answer. A different URL shape, a
39
- different time, or a different flag value each give a different result. The markup then does not
40
- match what the server sent, and hydration discards the server HTML. That failure is the
41
- one server-side rendering exists to prevent.
42
-
43
- ## Why a slot instead of a selector
44
-
45
- A browser-rendered flow points at a DOM selector, and the SDK inserts the component next
46
- to the element that it finds. That cannot work on a server, because a server has no DOM
47
- to search.
48
-
49
- A slot reverses that. `<ExperienceSlot name="page" />` is a mount point that you place in
50
- your own markup. An experience joins it when its target selector is `.picked-slot-<name>`.
51
- Your component tree decides where the content goes, so the server renders it in one pass.
52
-
53
- ## Why placements have an order
54
-
55
- More than one experience can point at the same slot, so the slot needs a rule. The order
56
- is:
57
-
58
- ```
59
- replace -> before -> prepend -> append -> after
60
- ```
61
-
62
- `replace` wins: an active experience with that placement renders alone. Every other active
63
- experience renders in the order above.
64
-
65
- The rule exists so the outcome does not depend on which experience came first. Two editors
66
- can add an experience to the same slot on the same day. The result then follows from the
67
- placements, and not from the database.
68
-
69
- ## Related
70
-
71
- - [Your first server-rendered page](/tutorials/first-server-rendered-page) — the whole
72
- path, in practice.
73
- - [Server snapshot](/reference/sdk/ssr/serialize) — every `serialize()` parameter.
74
- - [Slots and placements](/reference/sdk/ssr/slots-and-placements) — the exact rules for
75
- the order.
76
- - [About pages and flows](/explanation/pages-and-flows) — which kind you need.
@@ -1,71 +0,0 @@
1
- ---
2
- type: explanation
3
- layout: docs
4
- ---
5
-
6
- # About workspaces and versions
7
-
8
- Why can you not edit what your visitors see? Because Picked keeps two things separate on
9
- purpose: the work in progress, and the thing that it serves.
10
-
11
- ## The two states
12
-
13
- A **workspace** holds your changes. Edit a flow, a feature flag, a step, a field, an
14
- action, or a condition, and the change stays in the workspace. No visitor sees it.
15
-
16
- A **version** is what your visitors get. When you publish, Picked takes the current
17
- workspace and makes an immutable snapshot of it. A project serves exactly one version at a
18
- time, the live one.
19
-
20
- Everything else follows from that split.
21
-
22
- ## Why the snapshot is immutable
23
-
24
- A published version cannot change. That is what makes a roll-back safe. When you restore
25
- an earlier version, Picked moves the live pointer of the project and changes no data. The
26
- version that you restore is the exact version that was live before, and not a copy that
27
- Picked builds again.
28
-
29
- It is also what lets your draft continue. When you publish, your workspace stays
30
- editable, and a roll-back discards no draft. The two move at their own speed.
31
-
32
- ## The three workspace states
33
-
34
- - **Live** — the workspace whose snapshot the SDK serves. Each project has exactly one.
35
- - **Draft** — a workspace that no visitor sees. Edit it, see a preview of it, publish it.
36
- - **Archived** — a draft that you put to one side. It is still editable, but it is out of
37
- the default list.
38
-
39
- Picked keeps these two operations separate on purpose. Archive a draft when you are not
40
- certain about it. You cannot reverse a delete, but you can always unarchive.
41
-
42
- ## Why the publish modal shows a diff
43
-
44
- It is the one step in the dashboard that you cannot take back. It is therefore the one
45
- place that shows you exactly what changes. The modal compares the current workspace
46
- against the last published snapshot. It puts the changes into groups, and marks each row
47
- added, removed, or modified.
48
-
49
- The diff also carries a warning that a plain list of changes cannot give you. Some changes
50
- break other records. Remove a field while steps still point at it, and those steps
51
- now have an error. The preview shows that above the diff, before you publish and not after.
52
-
53
- The first publish of a workspace has no earlier snapshot to compare against, so the modal
54
- shows the contents instead of a diff.
55
-
56
- ## A preview does not reach production
57
-
58
- A preview sends the workspace state to the SDK in the query parameters. Your unpublished
59
- workspace therefore applies to your browser and to nothing else. The visitors on your live
60
- site see no change.
61
-
62
- One result of this matters. In a preview the SDK stores a feature flag decision in session
63
- storage and not in local storage. A preview allocation is therefore disposable, and it can
64
- differ from a production one. See
65
- [About feature flag allocation](/explanation/feature-flag-allocation).
66
-
67
- ## Related
68
-
69
- - [About how Picked works](/explanation/how-picked-works) — what a publish feeds.
70
- - [Workspaces](/reference/dashboard/workspaces) — the states and the settings.
71
- - [Publish history](/reference/dashboard/workspace-versioning) — the version list.
@@ -1,43 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to add a step, a field, an action, or a condition
7
-
8
- This guide shows you how to create the parts that a flow is built from. All four follow
9
- the same shape, and all four belong to the project: you can use one in more than one flow.
10
-
11
- ## Steps
12
-
13
- 1. Open a flow. The library is on the left of the flow builder.
14
- 2. Find the **Steps**, **Fields**, **Actions**, or **Conditions** section in it.
15
- 3. Click the **+** next to that section.
16
- 4. Enter a name. The dashboard makes the key from it.
17
- 5. Click the **Create** button for that kind: **Create step**, **Create field**,
18
- **Create action**, **Create condition**.
19
-
20
- The flow builder opens again, and the new one is in the library.
21
-
22
- **Fields** also has its own sidebar entry, so you can make a field without a flow. A step,
23
- an action, and a condition belong to a flow, and the library is the only way to reach
24
- them.
25
-
26
- The key is the identifier that your application uses. You set it one time, and you cannot
27
- change it later. Your visitors never see a name or a key.
28
-
29
- ## What each one needs after that
30
-
31
- | Kind | Set this next |
32
- | --- | --- |
33
- | Step | A **Layout**, such as `card`, `modal`, or `fullscreen`. |
34
- | Field | A **Label**, a type, and any validation rule. |
35
- | Action | Nothing in the dashboard. Register the handler in your code. |
36
- | Condition | The rule, in the **Logic** section of the inspector. |
37
-
38
- ## Related
39
-
40
- - [How to build a flow](/how-to/build-a-flow) — put it on the canvas.
41
- - [How to write a condition](/how-to/write-a-condition)
42
- - [How to register an action handler](/how-to/register-an-action-handler)
43
- - [How to reuse a step, a field, or an action](/how-to/reuse-a-step-field-or-action)