@sanity/presets 0.5.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,6 +24,8 @@ Presets are designed to be extended — add fields, groups, and map hooks as you
24
24
 
25
25
  **Prerequisites:** A Sanity Studio project with `sanity` installed. See the [getting started guide](https://www.sanity.io/docs/getting-started) if you're starting from scratch.
26
26
 
27
+ Presets give you schema types to add to a Studio you've already created — they don't scaffold a project or generate a schema from nothing.
28
+
27
29
  ```sh
28
30
  npm install @sanity/presets
29
31
  ```
@@ -36,40 +38,99 @@ pnpm add @sanity/presets
36
38
  yarn add @sanity/presets
37
39
  ```
38
40
 
39
- Import `createPresetsRegistry` and create a registry instance. The registry returns `define<Type>` functions that produce schema types:
41
+ ## Getting started
42
+
43
+ A working page-building schema, from scratch. The recommended layout keeps the registry in a module of its own, separate from your schema types and your Studio config:
44
+
45
+ ```
46
+ sanity.config.ts # Studio config — imports the assembled schema types
47
+ schemaTypes/
48
+ ├── presets.ts # creates the registry, exports the define* functions
49
+ ├── hero.ts # a custom type, modelled by hand
50
+ └── index.ts # assembles the schema types array
51
+ ```
52
+
53
+ ### 1. Create the registry
54
+
55
+ Call `createPresetsRegistry` once, in a module of its own. It returns the `define<Type>` functions that produce schema types. Export them for your schema files to import:
40
56
 
41
57
  ```ts
58
+ // schemaTypes/presets.ts
42
59
  import {createPresetsRegistry} from '@sanity/presets'
43
60
 
44
- const {defineLink, defineCta, defineSeo, defineImage, definePage} = createPresetsRegistry({
45
- link: {
46
- to: ['page', 'post'],
47
- },
61
+ export const {definePage, defineLink, defineCta, defineImage, defineRichText} =
62
+ createPresetsRegistry({
63
+ link: {
64
+ // Document types an internal link can point to. This cascades to
65
+ // every link — standalone, inside CTAs, inside rich text. See "Registry".
66
+ to: ['page'],
67
+ },
68
+ })
69
+ ```
70
+
71
+ Keep this in its own module rather than in `sanity.config.ts` or your schema index — creating the registry where your schema files import it back from leads to import cycles.
72
+
73
+ ### 2. Define your schema types
74
+
75
+ Import the `define<Type>` functions and use them to build your types. `definePage` produces a document type; the others produce object types you compose into it. Presets and hand-modelled types mix freely:
76
+
77
+ ```ts
78
+ // schemaTypes/index.ts
79
+ import {definePage, defineImage, defineCta, defineRichText} from './presets'
80
+ import {hero} from './hero'
81
+
82
+ export const schemaTypes = [
83
+ definePage({
84
+ name: 'page',
85
+ title: 'Page',
86
+ // Reference types by name, or inline a preset instance directly.
87
+ // See "Inline vs named types".
88
+ pageBuilderBlocks: ['hero', 'imageBlock', 'cta', 'richText'],
89
+ }),
90
+ hero,
91
+ defineImage({name: 'imageBlock', title: 'Image'}),
92
+ defineCta({name: 'cta', title: 'Call to action'}),
93
+ defineRichText({name: 'richText', title: 'Rich text'}),
94
+ ]
95
+ ```
96
+
97
+ The custom `hero` type is modelled by hand with `defineType`, the same as any non-preset type:
98
+
99
+ ```ts
100
+ // schemaTypes/hero.ts
101
+ import {defineField, defineType} from 'sanity'
102
+
103
+ export const hero = defineType({
104
+ name: 'hero',
105
+ title: 'Hero',
106
+ type: 'object',
107
+ fields: [
108
+ defineField({name: 'heading', title: 'Heading', type: 'string'}),
109
+ defineField({name: 'body', title: 'Body', type: 'text', rows: 3}),
110
+ ],
48
111
  })
49
112
  ```
50
113
 
51
- The `define<Type>` functions are used directly in your `schema.types` configuration, alongside standard `defineType` and `defineField` calls:
114
+ ### 3. Wire the schema into your config
115
+
116
+ Import the assembled array and pass it to `schema.types`:
52
117
 
53
118
  ```ts
119
+ // sanity.config.ts
54
120
  import {defineConfig} from 'sanity'
121
+ import {schemaTypes} from './schemaTypes'
55
122
 
56
123
  export default defineConfig({
57
- // ...
124
+ projectId: 'your-project-id',
125
+ dataset: 'production',
58
126
  schema: {
59
- types: [
60
- definePage({
61
- name: 'marketingPage',
62
- title: 'Marketing Page',
63
- // Each page builder block must be a type you've defined in your
64
- // schema. See "Use presets alongside custom types" for more.
65
- pageBuilderBlocks: ['hero', 'featureGrid'],
66
- }),
67
- // your other types...
68
- ],
127
+ types: schemaTypes,
69
128
  },
70
129
  })
71
130
  ```
72
131
 
132
+ That's a complete setup. From here, read [Concepts](#concepts) to understand the registry and composition, or [Usage](#usage) for the options each preset accepts.
133
+
73
134
  ## Concepts
74
135
 
75
136
  ### Registry
@@ -102,6 +163,37 @@ defineLink({
102
163
  })
103
164
  ```
104
165
 
166
+ ### Inline vs named types
167
+
168
+ Only `definePage` produces a document type. The other presets (`defineLink`, `defineCta`, `defineSeo`, `defineImage`, `defineRichText`) produce object and array types — building blocks meant to live _inside_ other types, not standalone documents. There are two ways to place them:
169
+
170
+ - **Inline** — call the preset directly where the type is used: inside a custom type's `fields`, or in a page's `pageBuilderBlocks`. This is the default; reach for it unless you have a reason not to.
171
+
172
+ ```ts
173
+ defineType({
174
+ name: 'blockquote',
175
+ type: 'object',
176
+ fields: [
177
+ defineField({name: 'quote', type: 'text'}),
178
+ // An inline link, defined right where it's used.
179
+ defineLink({name: 'source', title: 'Source'}),
180
+ ],
181
+ })
182
+ ```
183
+
184
+ - **Named** — register the preset once in `schema.types` with a `name`, then reference it elsewhere by that name string. Reach for this when you want one standardized definition reused in several places: define it once, and every reference stays in sync.
185
+
186
+ ```ts
187
+ // In schema.types, register a reusable CTA:
188
+ defineCta({name: 'cta', title: 'Call to action'})
189
+
190
+ // Elsewhere, refer to it by name:
191
+ pageBuilderBlocks: ['cta']
192
+ fields: [defineField({name: 'cta', type: 'cta'})]
193
+ ```
194
+
195
+ Default to inline; promote a preset to a named type only when reuse calls for it.
196
+
105
197
  ### Composition
106
198
 
107
199
  Presets can compose other presets. This means configuring one preset can affect others that depend on it.
@@ -157,13 +249,14 @@ The page preset produces a document type designed for page building. It includes
157
249
  definePage({
158
250
  name: 'marketingPage',
159
251
  title: 'Marketing Page',
160
- // Each page builder block must be a type you've defined in your schema.
161
- // See "Use presets alongside custom types" for more.
162
- pageBuilderBlocks: ['hero', 'featureGrid', 'testimonial'],
252
+ pageBuilderBlocks: [
253
+ defineImage({name: 'imageBlock', title: 'Image'}),
254
+ defineRichText({name: 'richText', title: 'Rich text'}),
255
+ ],
163
256
  })
164
257
  ```
165
258
 
166
- Each entry in `pageBuilderBlocks` is either a string referencing a type in your schema, or an inline schema type definition - typically a preset instance such as `defineImage({name: 'imageBlock'})`. Mix both freely.
259
+ Each entry in `pageBuilderBlocks` is either an inline schema type definition typically a preset instance, as above — or a string referencing a type defined elsewhere in your schema (see [Use presets alongside custom types](#use-presets-alongside-custom-types)). Mix both freely.
167
260
 
168
261
  Rich text presets work in `pageBuilderBlocks`, both inline (`defineRichText({...})`) and by name (`'richText'`). Documents store each rich text block under `content[].content`.
169
262
 
@@ -237,7 +330,7 @@ defineCta({
237
330
 
238
331
  ### SEO (search engine optimization)
239
332
 
240
- The SEO preset produces an object type for search engine metadata. It includes fields for a title, description, and Open Graph image with dimension validation.
333
+ The SEO preset produces an object type for search engine metadata. It includes fields for a title, description, and Open Graph image with a recommended size of 1200×630.
241
334
 
242
335
  ```ts
243
336
  defineSeo({
@@ -249,17 +342,17 @@ defineSeo({
249
342
 
250
343
  **Fields:**
251
344
 
252
- | Field | Type | Description |
253
- | ------------- | -------- | ------------------------------------------------------------------ |
254
- | `title` | `string` | Page title for search engines. Warns when exceeding 70 characters. |
255
- | `description` | `text` | Meta description. Warns when exceeding 150 characters. |
256
- | `ogImage` | `image` | Open Graph image. Validates dimensions are exactly 1200×630. |
345
+ | Field | Type | Description |
346
+ | ------------- | -------- | ----------------------------------------------------------------------------------------------------------- |
347
+ | `title` | `string` | Page title for search engines. Shows an info note past 70 characters, where search engines may truncate it. |
348
+ | `description` | `text` | Meta description. Shows an info note past 150 characters, where search engines may truncate it. |
349
+ | `ogImage` | `image` | Open Graph image. Shows a warning when dimensions aren't exactly 1200×630; recommended, not enforced. |
257
350
 
258
351
  The SEO preset is also composed into the page preset, where it appears as an inline object field in the Metadata group.
259
352
 
260
353
  ### Image
261
354
 
262
- The image preset produces an object type for images with optional alt text and caption fields. It includes built-in preview configuration.
355
+ The image preset produces an `image` type with optional alt text and caption fields. Hotspot is an option on the type itself; alt text and caption are added as fields. It includes built-in preview configuration.
263
356
 
264
357
  ```ts
265
358
  defineImage({
@@ -273,11 +366,10 @@ defineImage({
273
366
 
274
367
  **Fields:**
275
368
 
276
- | Field | Type | Description |
277
- | --------- | -------- | -------------------------------------------------------------------------------------- |
278
- | `image` | `image` | The image asset. Hotspot is enabled by default. |
279
- | `altText` | `string` | Alt text for accessibility. Enabled by default. Shows a validation warning when empty. |
280
- | `caption` | `text` | Image caption. Enabled by default. |
369
+ | Field | Type | Description |
370
+ | --------- | -------- | ------------------------------------------------------------------------------------- |
371
+ | `altText` | `string` | Alt text for accessibility. Enabled by default. Shows a warning encouraging alt text. |
372
+ | `caption` | `text` | Image caption. Enabled by default. |
281
373
 
282
374
  **Options:**
283
375
 
@@ -408,9 +500,7 @@ Rather than reaching for [map hooks](#map-hooks), use the `fields` and `groups`
408
500
  definePage({
409
501
  name: 'blogPost',
410
502
  title: 'Blog Post',
411
- // These types must be defined in your schema.
412
- // See "Use presets alongside custom types" for more.
413
- pageBuilderBlocks: ['richText', defineImage({name: 'imageBlock'})],
503
+ pageBuilderBlocks: [defineRichText({name: 'richText'}), defineImage({name: 'imageBlock'})],
414
504
  groups: [{name: 'settings', title: 'Settings'}],
415
505
  fields: [
416
506
  defineField({