@picked/client 0.0.1-dev.1786072899095 → 0.0.1-dev.1786601464574
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/api-C8B96Kwv.js +22 -0
- package/dist/api-DS7fA9kj.cjs +1 -0
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
- package/dist/cjs/server/index.js +1 -1
- package/dist/docs/explanation/content-references.md +99 -0
- package/dist/docs/explanation/how-picked-works.md +25 -3
- package/dist/docs/explanation/the-content-model.md +38 -28
- package/dist/docs/how-to/authenticate-the-cli.md +95 -0
- package/dist/docs/how-to/create-a-content-entry.md +48 -0
- package/dist/docs/how-to/define-a-page-layout.md +12 -5
- package/dist/docs/how-to/install-the-sdk.md +7 -0
- package/dist/docs/how-to/point-one-entry-at-another.md +61 -0
- package/dist/docs/how-to/read-a-referenced-entry.md +111 -0
- package/dist/docs/how-to/reuse-a-section.md +26 -10
- package/dist/docs/how-to/switch-workspaces.md +123 -0
- package/dist/docs/index.md +1 -1
- package/dist/docs/reference/dashboard/content/blocks.mdx +57 -0
- package/dist/docs/reference/dashboard/content/content-entries.mdx +61 -10
- package/dist/docs/reference/dashboard/content/models.mdx +108 -0
- package/dist/docs/reference/dashboard/content/pages.mdx +4 -3
- package/dist/docs/reference/dashboard/fields.mdx +1 -1
- package/dist/docs/reference/dashboard/steps.mdx +2 -2
- package/dist/docs/reference/delivery-api/experience-content.md +68 -13
- package/dist/docs/reference/delivery-api/workspace-schema.md +74 -0
- package/dist/docs/reference/glossary.md +13 -5
- package/dist/docs/reference/management-api/error-handling.md +2 -2
- package/dist/docs/reference/sdk/content.md +216 -0
- package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +51 -3
- package/dist/docs/reference/sdk/ssr/serialize.md +6 -3
- package/dist/docs/reference/sdk/type-generation.md +130 -0
- package/dist/docs/reference/tools/cli.md +141 -0
- package/dist/docs/reference/tools/vite-plugin.md +90 -8
- package/dist/docs/tutorials/first-api-call.md +1 -1
- package/dist/docs/tutorials/first-server-rendered-page.mdx +1 -1
- package/dist/esm/index.js +496 -432
- package/dist/esm/plugins/dynamic-experiences/index.js +5 -3
- package/dist/esm/server/index.js +43 -46
- package/dist/plugin-C8hWW3ed.js +157 -0
- package/dist/plugin-Dtg2sOad.cjs +1 -0
- package/dist/provider-BEpRDCyr.js +69 -0
- package/dist/provider-ixdOyYTA.cjs +1 -0
- package/dist/registry-C1t8l3t9.cjs +1 -0
- package/dist/registry-CXZv0uLg.js +18 -0
- package/dist/types/data-source/api.d.ts +60 -0
- package/dist/types/data-source/api.d.ts.map +1 -0
- package/dist/types/data-source/provider.d.ts +90 -0
- package/dist/types/data-source/provider.d.ts.map +1 -0
- package/dist/types/data-source/registry.d.ts +26 -0
- package/dist/types/data-source/registry.d.ts.map +1 -0
- package/dist/types/data-source/virtual-data.d.ts +19 -0
- package/dist/types/data-source/virtual-data.d.ts.map +1 -0
- package/dist/types/entities/content/reference.d.ts +101 -0
- package/dist/types/entities/content/reference.d.ts.map +1 -0
- package/dist/types/entities/response/response.d.ts +22 -6
- package/dist/types/entities/response/response.d.ts.map +1 -1
- package/dist/types/exports.d.ts +2 -0
- package/dist/types/exports.d.ts.map +1 -1
- package/dist/types/form/create-submit-pipeline.d.ts +32 -3
- package/dist/types/form/create-submit-pipeline.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/picked.d.ts +68 -4
- package/dist/types/picked.d.ts.map +1 -1
- package/dist/types/ping.d.ts +4 -3
- package/dist/types/ping.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/index.d.ts +2 -1
- package/dist/types/plugins/dynamic-experiences/index.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/plugin.d.ts +9 -40
- package/dist/types/plugins/dynamic-experiences/plugin.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/types.d.ts +22 -129
- package/dist/types/plugins/dynamic-experiences/types.d.ts.map +1 -1
- package/dist/types/schema-registry.d.ts +190 -0
- package/dist/types/schema-registry.d.ts.map +1 -0
- package/dist/types/server/index.d.ts +2 -2
- package/dist/types/server/index.d.ts.map +1 -1
- package/dist/types/server/serialize.d.ts +37 -34
- package/dist/types/server/serialize.d.ts.map +1 -1
- package/dist/types/typed-content.d.ts +17 -0
- package/dist/types/typed-content.d.ts.map +1 -0
- package/dist/types/utils/picked-config.d.ts +19 -1
- package/dist/types/utils/picked-config.d.ts.map +1 -1
- package/dist/version-BLzNWQ-j.cjs +1 -0
- package/dist/version-IAAIvoH9.js +4 -0
- package/package.json +5 -3
- package/dist/api-BzK4kXRt.js +0 -38
- package/dist/api-CgENjKwJ.cjs +0 -1
- package/dist/docs/reference/dashboard/content/layouts.mdx +0 -62
- package/dist/docs/reference/dashboard/content/sections.mdx +0 -28
- package/dist/plugin-DJjtc5df.js +0 -252
- package/dist/plugin-jHxSAqGG.cjs +0 -1
- package/dist/types/utils/api.d.ts +0 -25
- package/dist/types/utils/api.d.ts.map +0 -1
- package/dist/types/utils/client-headers.d.ts +0 -2
- package/dist/types/utils/client-headers.d.ts.map +0 -1
|
@@ -5,52 +5,61 @@ layout: docs
|
|
|
5
5
|
|
|
6
6
|
# About the content model
|
|
7
7
|
|
|
8
|
-
Picked splits your content into three pieces: a
|
|
8
|
+
Picked splits your content into three pieces: a Model, a Block, and a content entry.
|
|
9
9
|
Why three, when a page editor needs only one?
|
|
10
10
|
|
|
11
11
|
## Schema and data are separate
|
|
12
12
|
|
|
13
|
-
A **
|
|
13
|
+
A **Model** is a schema. It sets which fields a piece of content can hold, and it holds
|
|
14
14
|
no data itself. A **content entry** is one instance of that schema, filled with real
|
|
15
15
|
values.
|
|
16
16
|
|
|
17
|
-
One
|
|
17
|
+
One Model backs many entries. Describe a campaign page one time, then make many pages
|
|
18
18
|
from it. Each entry carries its own title, its own body, and its own image, but they all
|
|
19
19
|
share the shape.
|
|
20
20
|
|
|
21
21
|
That split is also what lets your code depend on content that it never saw. Your component
|
|
22
|
-
reads `content.title` because the
|
|
23
|
-
comes from that
|
|
22
|
+
reads `content.title` because the Model promises a `title`. It works for every entry that
|
|
23
|
+
comes from that Model.
|
|
24
24
|
|
|
25
|
-
## A
|
|
25
|
+
## A category gives a Model a role
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
| Layout | It gives shape to | Who renders it |
|
|
31
|
-
| --- | --- | --- |
|
|
32
|
-
| Page layout | A standalone [Page](/reference/dashboard/content/pages). | The SDK renders the entry on your server. |
|
|
33
|
-
| Step layout | One [Step](/reference/dashboard/steps) inside a Flow. | The Step renders the entry in the browser. |
|
|
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.
|
|
34
30
|
|
|
35
31
|
The category is fixed because it decides where the SDK renders the entry. That is not a
|
|
36
|
-
property you can change under an entry that exists already.
|
|
37
|
-
|
|
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.
|
|
38
41
|
|
|
39
|
-
## A
|
|
42
|
+
## A Block is a schema fragment
|
|
40
43
|
|
|
41
|
-
A
|
|
42
|
-
inside one or more
|
|
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.
|
|
43
46
|
|
|
44
|
-
Define a hero one time as a
|
|
45
|
-
|
|
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.
|
|
46
49
|
|
|
47
|
-
This is the reason
|
|
48
|
-
structure again in each
|
|
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
|
|
49
52
|
argument for one fact in one place that runs through the rest of this documentation.
|
|
50
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
|
+
|
|
51
60
|
## Why a schema change does not migrate your data
|
|
52
61
|
|
|
53
|
-
Change a
|
|
62
|
+
Change a Model or a Block, and Picked does not rewrite the entries behind it. An entry
|
|
54
63
|
that no longer matches its schema becomes invalid, and the dashboard shows an error on
|
|
55
64
|
each field that does not fit.
|
|
56
65
|
|
|
@@ -58,20 +67,21 @@ That is deliberate. An automatic change must decide what a new required field ho
|
|
|
58
67
|
every entry that came before it. Any value that it chooses is content that nobody wrote.
|
|
59
68
|
Picked reports the error instead, and you correct it.
|
|
60
69
|
|
|
61
|
-
The cost is real. After a schema change, check every entry that uses that
|
|
70
|
+
The cost is real. After a schema change, check every entry that uses that Model and fix
|
|
62
71
|
each error before you publish. Picked serves valid content only, so an entry with an error
|
|
63
72
|
does not reach a visitor.
|
|
64
73
|
|
|
65
74
|
## An error points at the exact field
|
|
66
75
|
|
|
67
76
|
A validation error carries a path in JSON style, such as `sections[0].data.title`. The
|
|
68
|
-
path holds through nested groups, repeated fields, and
|
|
77
|
+
path holds through nested groups, repeated fields, and Blocks. An error inside a
|
|
69
78
|
repeated group therefore tells you which item in that group holds it.
|
|
70
79
|
|
|
71
80
|
## Related
|
|
72
81
|
|
|
73
|
-
- [
|
|
74
|
-
- [
|
|
82
|
+
- [Models](/reference/dashboard/content/models) — every field type.
|
|
83
|
+
- [Blocks](/reference/dashboard/content/blocks) — the reusable fragments.
|
|
75
84
|
- [Content entries](/reference/dashboard/content/content-entries) — the editor and the
|
|
76
85
|
validation.
|
|
77
|
-
- [About
|
|
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.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to authenticate the CLI
|
|
7
|
+
|
|
8
|
+
This guide shows you how to install `@picked/cli` and sign it in. Commands that read your
|
|
9
|
+
organizations, projects, and workspaces then know who you are. It expects a Picked account
|
|
10
|
+
and a project directory to work in.
|
|
11
|
+
|
|
12
|
+
## 1. Install the CLI
|
|
13
|
+
|
|
14
|
+
:::code-group
|
|
15
|
+
|
|
16
|
+
```bash [npm]
|
|
17
|
+
npm install --save-dev @picked/cli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```bash [pnpm]
|
|
21
|
+
pnpm add -D @picked/cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```bash [yarn]
|
|
25
|
+
yarn add -D @picked/cli
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
:::
|
|
29
|
+
|
|
30
|
+
The binary is `picked`. Run it from the directory that holds your `picked.config.ts`, so it
|
|
31
|
+
reads your configuration and writes your selection next to it.
|
|
32
|
+
|
|
33
|
+
## 2. Sign in
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
picked login
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The command opens your browser for a one-time sign-in and prints your identity:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Opening your browser to sign in...
|
|
43
|
+
https://api.picked.app/…/oauth/authorize?…
|
|
44
|
+
Logged in as you@example.com (https://api.picked.app)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The CLI stores the session in `~/.picked/auth/<origin>.json`, outside any repository, with
|
|
48
|
+
file mode `600`. It refreshes the session as it nears expiry.
|
|
49
|
+
|
|
50
|
+
## 3. Confirm the session
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
picked whoami
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
you@example.com (https://api.picked.app)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Each command acts on the API origin your current directory resolves to, and on no other. To
|
|
61
|
+
end the session for that origin:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
picked logout
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
Logged out of https://api.picked.app.
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Run the CLI in CI
|
|
72
|
+
|
|
73
|
+
CI has no browser, so give the CLI a token instead of a session. `PICKED_TOKEN` takes
|
|
74
|
+
precedence over any stored session:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
PICKED_TOKEN="$PICKED_ACCESS_TOKEN" picked generate types --check
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If an API deployment does not offer OAuth client registration, `picked login` fails and
|
|
81
|
+
tells you to set `PICKED_TOKEN`. It falls back to no other flow.
|
|
82
|
+
|
|
83
|
+
:::note
|
|
84
|
+
This is a developer session for local tooling. It is not the same as an
|
|
85
|
+
[API key](/reference/dashboard/api-keys), which authenticates server-to-server delivery and
|
|
86
|
+
management calls, or [dashboard sign-in](/reference/management-api/authentication). Use an
|
|
87
|
+
API key for an application; use `picked login` for the CLI on your machine.
|
|
88
|
+
:::
|
|
89
|
+
|
|
90
|
+
## Related
|
|
91
|
+
|
|
92
|
+
- [CLI](/reference/tools/cli) — every command, flag, and environment variable.
|
|
93
|
+
- [How to switch workspaces](/how-to/switch-workspaces) — the draft-preview workflow.
|
|
94
|
+
- [How to create and revoke an API key](/how-to/create-and-revoke-an-api-key) — credentials
|
|
95
|
+
for applications.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to create a content entry
|
|
7
|
+
|
|
8
|
+
This guide shows you how to make one instance of a Model and fill it with data. You need
|
|
9
|
+
a Model first. See [How to define a page layout](/how-to/define-a-page-layout).
|
|
10
|
+
|
|
11
|
+
A Page makes its own entry when you create the page. Use this guide for the content that
|
|
12
|
+
no Page and no Step owns, such as an author or a product.
|
|
13
|
+
|
|
14
|
+
## 1. Open the entries list
|
|
15
|
+
|
|
16
|
+
1. Open your workspace.
|
|
17
|
+
2. Click **CMS** in the sidebar.
|
|
18
|
+
3. Click **Content entries**.
|
|
19
|
+
|
|
20
|
+
## 2. Create the entry
|
|
21
|
+
|
|
22
|
+
1. Click **New content**.
|
|
23
|
+
2. Choose the **Model** for the entry.
|
|
24
|
+
3. Fill in each field. The form comes from the schema of the Model.
|
|
25
|
+
4. Click **Create entry**.
|
|
26
|
+
|
|
27
|
+
The Model is fixed when you create the entry. To move content to another Model, make a
|
|
28
|
+
new entry and copy the values across.
|
|
29
|
+
|
|
30
|
+
## 3. Correct every error
|
|
31
|
+
|
|
32
|
+
An invalid field shows an error next to it while you edit. The error carries the path to
|
|
33
|
+
the exact field. Correct each one before you publish, because Picked serves valid content
|
|
34
|
+
only.
|
|
35
|
+
|
|
36
|
+
## Find an entry again
|
|
37
|
+
|
|
38
|
+
The entries list shows a title for each entry. The title is the first single-line text
|
|
39
|
+
field of the entry. It shows the entry id when no such field holds a value.
|
|
40
|
+
|
|
41
|
+
Use the **Model** filter to narrow the list to one Model.
|
|
42
|
+
|
|
43
|
+
## Related
|
|
44
|
+
|
|
45
|
+
- [Content entries](/reference/dashboard/content/content-entries) — the editor reference.
|
|
46
|
+
- [Models](/reference/dashboard/content/models) — every field type.
|
|
47
|
+
- [How to point one entry at another](/how-to/point-one-entry-at-another)
|
|
48
|
+
- [How to publish a workspace](/how-to/publish-a-workspace)
|
|
@@ -5,8 +5,8 @@ layout: docs
|
|
|
5
5
|
|
|
6
6
|
# How to define a page layout
|
|
7
7
|
|
|
8
|
-
This guide shows you how to define the shape of a page. A layout sets which fields a
|
|
9
|
-
can hold, and it holds no data itself.
|
|
8
|
+
This guide shows you how to define the shape of a page. A page layout sets which fields a
|
|
9
|
+
page can hold, and it holds no data itself.
|
|
10
10
|
|
|
11
11
|
## Steps
|
|
12
12
|
|
|
@@ -19,7 +19,7 @@ can hold, and it holds no data itself.
|
|
|
19
19
|
6. Add your fields. Choose a type for each one.
|
|
20
20
|
7. Click **Create model**.
|
|
21
21
|
|
|
22
|
-
The category is fixed when you create the
|
|
22
|
+
The category is fixed when you create the Model. You cannot change it later.
|
|
23
23
|
|
|
24
24
|
## Make a field repeatable
|
|
25
25
|
|
|
@@ -31,9 +31,16 @@ for a gallery, or for a list of features.
|
|
|
31
31
|
Add a **Group** field to hold a set of fields under one key. Make the group repeatable to
|
|
32
32
|
describe a list of objects, such as a list of feature cards.
|
|
33
33
|
|
|
34
|
+
## Define content with no layout role
|
|
35
|
+
|
|
36
|
+
A Model needs no category. Leave **Category** as **None (general content)** for content
|
|
37
|
+
that no Page and no Step renders, such as an author or a product. Reach such a Model
|
|
38
|
+
under **CMS** in the sidebar, and point at its entries with a **Reference** field.
|
|
39
|
+
|
|
34
40
|
## Related
|
|
35
41
|
|
|
36
42
|
- [About the content model](/explanation/the-content-model) — why the schema and the data
|
|
37
43
|
are separate.
|
|
38
|
-
- [
|
|
39
|
-
- [How to reuse a section](/how-to/reuse-a-section)
|
|
44
|
+
- [Models](/reference/dashboard/content/models) — every field type.
|
|
45
|
+
- [How to reuse a section](/how-to/reuse-a-section)
|
|
46
|
+
- [How to point one entry at another](/how-to/point-one-entry-at-another)
|
|
@@ -22,6 +22,13 @@ npm install @picked/client @picked/svelte effector
|
|
|
22
22
|
|
|
23
23
|
:::
|
|
24
24
|
|
|
25
|
+
:::note
|
|
26
|
+
`picked` is a shorter name for the same client. `npm install picked` gives you
|
|
27
|
+
`createClient` from `picked` and the `picked.config` helpers from `picked/config`. It also
|
|
28
|
+
gives you the `picked` command. npm adds `@picked/client` with it, which is where the
|
|
29
|
+
generated types attach.
|
|
30
|
+
:::
|
|
31
|
+
|
|
25
32
|
## 2. Create and start the client
|
|
26
33
|
|
|
27
34
|
:::code-group
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to point one entry at another
|
|
7
|
+
|
|
8
|
+
This guide shows you how to point one content entry at another, such as a product at its
|
|
9
|
+
category. You need two Models: the one that holds the pointer, and the one that the
|
|
10
|
+
pointer reaches.
|
|
11
|
+
|
|
12
|
+
## 1. Create the target Model
|
|
13
|
+
|
|
14
|
+
1. Click **CMS** in the sidebar, then **Models**.
|
|
15
|
+
2. Click **New model**.
|
|
16
|
+
3. Enter a **Name** and a **Key**, such as `category`.
|
|
17
|
+
4. Leave **Category** as **None (general content)**.
|
|
18
|
+
5. Add your fields.
|
|
19
|
+
6. Click **Create model**.
|
|
20
|
+
|
|
21
|
+
## 2. Add a Reference field
|
|
22
|
+
|
|
23
|
+
1. Open the Model that holds the pointer.
|
|
24
|
+
2. Drag a **Reference** property onto the schema.
|
|
25
|
+
3. Enter a **Name** and a **Key**, such as `category`.
|
|
26
|
+
4. Set **Target Model** to the Model from step 1.
|
|
27
|
+
5. Click **Save**.
|
|
28
|
+
|
|
29
|
+
Turn on **repeatable** for a field that points at more than one entry. Leave **Target
|
|
30
|
+
Model** as **Any Model** to accept an entry of any Model in the workspace.
|
|
31
|
+
|
|
32
|
+
## 3. Choose a target on an entry
|
|
33
|
+
|
|
34
|
+
1. Open a content entry that uses the Model.
|
|
35
|
+
2. Find your Reference field.
|
|
36
|
+
3. Click **Choose entry**.
|
|
37
|
+
4. Search for the entry.
|
|
38
|
+
5. Choose the entry.
|
|
39
|
+
6. Click **Save**.
|
|
40
|
+
|
|
41
|
+
Use **Change entry** to point the field somewhere else. Use **Clear** to remove the
|
|
42
|
+
pointer. **Clear** deletes no content.
|
|
43
|
+
|
|
44
|
+
## Delete a target
|
|
45
|
+
|
|
46
|
+
Picked does not delete an entry while another entry points at it. Clear the reference on
|
|
47
|
+
each entry that points at the target, then delete the target.
|
|
48
|
+
|
|
49
|
+
The same rule holds for a Model. Remove the Reference field that holds it as its **Target
|
|
50
|
+
Model** first.
|
|
51
|
+
|
|
52
|
+
## Read it in your code
|
|
53
|
+
|
|
54
|
+
The pointer and the entry travel separately. See
|
|
55
|
+
[How to read a referenced entry](/how-to/read-a-referenced-entry).
|
|
56
|
+
|
|
57
|
+
## Related
|
|
58
|
+
|
|
59
|
+
- [About content references](/explanation/content-references) — why a reference is a pointer.
|
|
60
|
+
- [Models](/reference/dashboard/content/models) — the field and its options.
|
|
61
|
+
- [Content entries](/reference/dashboard/content/content-entries) — the editor reference.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: how-to
|
|
3
|
+
layout: docs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# How to read a referenced entry
|
|
7
|
+
|
|
8
|
+
This guide shows you how to read the content that a
|
|
9
|
+
[Reference field](/reference/dashboard/content/models#reference-fields) points at. You
|
|
10
|
+
need a component that renders a step first. See
|
|
11
|
+
[How to render a step form](/how-to/render-a-step-form).
|
|
12
|
+
|
|
13
|
+
A Reference field holds a pointer, and not the content. The entry travels beside the
|
|
14
|
+
content of the step, so you resolve the pointer against the content of the client.
|
|
15
|
+
|
|
16
|
+
## 1. Resolve a single reference
|
|
17
|
+
|
|
18
|
+
Pass the raw field value to `useReference()` in React, or to `getReference()` in Svelte.
|
|
19
|
+
|
|
20
|
+
:::code-group
|
|
21
|
+
|
|
22
|
+
```tsx [React]
|
|
23
|
+
import { useUnit } from 'effector-react'
|
|
24
|
+
import { useReference, useStepContent } from '@picked/react/hooks'
|
|
25
|
+
|
|
26
|
+
export function ProductCategory() {
|
|
27
|
+
const content = useStepContent()
|
|
28
|
+
const category = useUnit(useReference(content?.category))
|
|
29
|
+
|
|
30
|
+
if (!category) return null
|
|
31
|
+
|
|
32
|
+
return <span>{String(category.data.name ?? '')}</span>
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```svelte [Svelte]
|
|
37
|
+
<script lang="ts">
|
|
38
|
+
import { getStepContent, getReference } from '@picked/svelte/hooks'
|
|
39
|
+
|
|
40
|
+
const content = getStepContent()
|
|
41
|
+
const category = getReference(content.map((c) => c?.category ?? null, { skipVoid: false }))
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{#if $category}
|
|
45
|
+
<span>{$category.data.name ?? ''}</span>
|
|
46
|
+
{/if}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
:::
|
|
50
|
+
|
|
51
|
+
In Svelte, pass a store and not a plain value. Content arrives after the component
|
|
52
|
+
starts. A plain value therefore holds the result at "not set".
|
|
53
|
+
|
|
54
|
+
## 2. Resolve a repeatable reference
|
|
55
|
+
|
|
56
|
+
Use `useReferences()` or `getReferences()`. They give a list in field order.
|
|
57
|
+
|
|
58
|
+
:::code-group
|
|
59
|
+
|
|
60
|
+
```tsx [React]
|
|
61
|
+
import { useUnit } from 'effector-react'
|
|
62
|
+
import { useReferences, useStepContent } from '@picked/react/hooks'
|
|
63
|
+
|
|
64
|
+
export function ProductCategories() {
|
|
65
|
+
const content = useStepContent()
|
|
66
|
+
const categories = useUnit(useReferences(content?.categories))
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<ul>
|
|
70
|
+
{categories.map((category) => (
|
|
71
|
+
<li key={category.id}>{String(category.data.name ?? '')}</li>
|
|
72
|
+
))}
|
|
73
|
+
</ul>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```svelte [Svelte]
|
|
79
|
+
<script lang="ts">
|
|
80
|
+
import { getStepContent, getReferences } from '@picked/svelte/hooks'
|
|
81
|
+
|
|
82
|
+
const content = getStepContent()
|
|
83
|
+
const categories = getReferences(content.map((c) => c?.categories ?? null, { skipVoid: false }))
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<ul>
|
|
87
|
+
{#each $categories as category (category.id)}
|
|
88
|
+
<li>{category.data.name ?? ''}</li>
|
|
89
|
+
{/each}
|
|
90
|
+
</ul>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
:::
|
|
94
|
+
|
|
95
|
+
The list holds no empty places, so you need no check for each item.
|
|
96
|
+
|
|
97
|
+
## Handle a target that does not resolve
|
|
98
|
+
|
|
99
|
+
A single reference gives an empty result when Picked cannot resolve the target. A
|
|
100
|
+
repeatable reference leaves the item out of the list.
|
|
101
|
+
|
|
102
|
+
This happens when somebody deleted the target, when the target belongs to another
|
|
103
|
+
workspace, or when the chain of references is deeper than the limit.
|
|
104
|
+
|
|
105
|
+
Render something else for the empty case, as the React example above does.
|
|
106
|
+
|
|
107
|
+
## Related
|
|
108
|
+
|
|
109
|
+
- [Content](/reference/sdk/content) — every hook and its return type.
|
|
110
|
+
- [About content references](/explanation/content-references) — why the entry travels separately.
|
|
111
|
+
- [How to point one entry at another](/how-to/point-one-entry-at-another) — the dashboard side.
|
|
@@ -6,27 +6,42 @@ layout: docs
|
|
|
6
6
|
# How to reuse a section
|
|
7
7
|
|
|
8
8
|
This guide shows you how to define a common structure one time and use it in more than
|
|
9
|
-
one
|
|
9
|
+
one Model.
|
|
10
10
|
|
|
11
|
-
## Create
|
|
11
|
+
## 1. Create the section
|
|
12
12
|
|
|
13
|
-
1.
|
|
14
|
-
2. Click **
|
|
13
|
+
1. Click **Pages** in the sidebar.
|
|
14
|
+
2. Click **Page Sections**.
|
|
15
15
|
3. Click **New block**.
|
|
16
16
|
4. Enter a **Name** and a **Key**.
|
|
17
17
|
5. Add your fields.
|
|
18
18
|
6. Click **Create block**.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
The **Category** is **Section** already, because you opened the list from **Page
|
|
21
|
+
Sections**.
|
|
22
|
+
|
|
23
|
+
## 2. Accept the section in a Model
|
|
21
24
|
|
|
22
25
|
1. Open a page layout or a step layout.
|
|
23
|
-
2. Add a **
|
|
24
|
-
3.
|
|
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
|
|
25
36
|
|
|
26
|
-
|
|
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**.
|
|
27
42
|
|
|
28
43
|
:::warning
|
|
29
|
-
An edit to a
|
|
44
|
+
An edit to a Block does not migrate the entries that use it. Check each affected content
|
|
30
45
|
entry again, and correct every field error before you publish.
|
|
31
46
|
:::
|
|
32
47
|
|
|
@@ -34,4 +49,5 @@ entry again, and correct every field error before you publish.
|
|
|
34
49
|
|
|
35
50
|
- [About the content model](/explanation/the-content-model) — why a schema change does not
|
|
36
51
|
migrate your data.
|
|
37
|
-
- [
|
|
52
|
+
- [Blocks](/reference/dashboard/content/blocks) — the reference.
|
|
53
|
+
- [Models](/reference/dashboard/content/models) — every field type.
|
|
@@ -0,0 +1,123 @@
|
|
|
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`. For CI, set `PICKED_TOKEN` instead — 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_TOKEN="$TOKEN" \
|
|
103
|
+
PICKED_PROJECT_ID=proj_a1b2 \
|
|
104
|
+
PICKED_PREVIEW_TOKEN="$DRAFT_TOKEN" \
|
|
105
|
+
picked generate types --check
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`PICKED_PREVIEW_TOKEN` applies only when the resolved `source` is `preview`. See the
|
|
109
|
+
[CLI environment variables](/reference/tools/cli#environment-variables) for the full
|
|
110
|
+
precedence order.
|
|
111
|
+
|
|
112
|
+
:::note
|
|
113
|
+
A preview token is a long-lived credential for one workspace. Keep it out of the version
|
|
114
|
+
control system, as you do with each other credential. Git ignores `.picked/settings.json`
|
|
115
|
+
for this reason, because `picked workspace use` writes a token there.
|
|
116
|
+
:::
|
|
117
|
+
|
|
118
|
+
## Related
|
|
119
|
+
|
|
120
|
+
- [CLI](/reference/tools/cli) — every command and flag.
|
|
121
|
+
- [Workspaces](/reference/dashboard/workspaces) — Live, Draft, and Archived states.
|
|
122
|
+
- [Type generation](/reference/sdk/type-generation) — how the schema becomes types.
|
|
123
|
+
- [Preview, cache, and crawlers](/reference/delivery-api/preview-caching-crawling) — preview tokens on the Delivery API.
|
package/dist/docs/index.md
CHANGED
|
@@ -25,7 +25,7 @@ Then:
|
|
|
25
25
|
|
|
26
26
|
- **[Build](/how-to/create-an-experience)** — experiences, flows, conditions, and A/B
|
|
27
27
|
tests.
|
|
28
|
-
- **[Content](/how-to/define-a-page-layout)** —
|
|
28
|
+
- **[Content](/how-to/define-a-page-layout)** — Models, Blocks, entries, pages, and assets.
|
|
29
29
|
- **[Publish](/how-to/publish-a-workspace)** — preview, publish, and roll back.
|
|
30
30
|
- **[Administer and measure](/how-to/invite-and-remove-members)** — members, API keys,
|
|
31
31
|
analytics, and the tools that connect Picked to Google Tag Manager and to an AI tool.
|