sanity-plugin-seofields 1.0.5 → 1.0.7

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
@@ -3,19 +3,20 @@
3
3
  [![npm version](https://badge.fury.io/js/sanity-plugin-seofields.svg)](https://badge.fury.io/js/sanity-plugin-seofields)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- A comprehensive Sanity Studio v3 plugin to manage SEO fields like meta titles, descriptions, Open Graph tags, and Twitter Cards for structured, search-optimized content.
6
+ A comprehensive Sanity Studio v3 plugin to manage SEO fields like meta titles, descriptions, Open Graph tags, and X (Formerly Twitter) Cards for structured, search-optimized content.
7
7
 
8
8
  ## ✨ Features
9
9
 
10
10
  - 🎯 **Meta Tags**: Title, description, keywords, and canonical URLs
11
11
  - 📱 **Open Graph**: Complete social media sharing optimization
12
- - 🐦 **Twitter Cards**: Twitter-specific meta tags with image support
12
+ - 🐦 **X (Formerly Twitter) Cards**: X-specific meta tags with image support
13
13
  - 🤖 **Robots Control**: Index/follow settings for search engines
14
14
  - 🖼️ **Image Management**: Optimized image handling for social sharing
15
15
  - 📋 **Live Preview**: Real-time SEO preview as you edit
16
16
  - 🔧 **TypeScript Support**: Full type definitions included
17
17
  - 📊 **Custom Attributes**: Flexible meta attribute system
18
18
  - ✅ **Validation**: Built-in character limits and best practices
19
+ - 🎛️ **Field Visibility**: Hide sitewide fields on specific content types
19
20
 
20
21
  ## 📦 Installation
21
22
 
@@ -112,7 +113,7 @@ export default defineType({
112
113
  }),
113
114
  defineField({
114
115
  name: 'twitterCard',
115
- title: 'Twitter Card',
116
+ title: 'X (Formerly Twitter) Card',
116
117
  type: 'twitter',
117
118
  }),
118
119
  defineField({
@@ -130,7 +131,7 @@ export default defineType({
130
131
  | --------------- | ------------------------- | -------------------------------- |
131
132
  | `seoFields` | Complete SEO package | Main SEO fields for any document |
132
133
  | `openGraph` | Open Graph meta tags | Social media sharing |
133
- | `twitter` | Twitter Card settings | Twitter-specific optimization |
134
+ | `twitter` | X (Formerly Twitter) Card settings | X-specific optimization |
134
135
  | `metaTag` | Custom meta attributes | Advanced meta tag management |
135
136
  | `metaAttribute` | Individual meta attribute | Building custom meta tags |
136
137
  | `robots` | Search engine directives | Control indexing and crawling |
@@ -151,7 +152,7 @@ export default defineConfig({
151
152
 
152
153
  ### Advanced Configuration
153
154
 
154
- You can customize field titles and descriptions, and control SEO preview functionality:
155
+ You can customize field titles and descriptions, control SEO preview functionality, and manage field visibility:
155
156
 
156
157
  ```typescript
157
158
  import seofields, {SeoFieldsPluginConfig} from 'sanity-plugin-seofields'
@@ -182,6 +183,17 @@ export default defineConfig({
182
183
  description: 'Keywords that describe the content of this page',
183
184
  },
184
185
  },
186
+ // Hide sitewide fields on specific content types
187
+ fieldVisibility: {
188
+ page: {
189
+ hiddenFields: ['openGraphSiteName', 'twitterSite']
190
+ },
191
+ post: {
192
+ hiddenFields: ['openGraphSiteName', 'twitterSite']
193
+ }
194
+ },
195
+ // Or hide fields globally
196
+ defaultHiddenFields: ['openGraphSiteName', 'twitterSite']
185
197
  } satisfies SeoFieldsPluginConfig),
186
198
  ],
187
199
  })
@@ -189,10 +201,12 @@ export default defineConfig({
189
201
 
190
202
  ### Configuration Options
191
203
 
192
- | Option | Type | Default | Description |
193
- | ---------------- | --------- | ------- | ------------------------------------------- |
194
- | `seoPreview` | `boolean` | `true` | Enable/disable the live SEO preview feature |
195
- | `fieldOverrides` | `object` | `{}` | Customize field titles and descriptions |
204
+ | Option | Type | Default | Description |
205
+ | --------------------- | --------- | ------- | ------------------------------------------- |
206
+ | `seoPreview` | `boolean` | `true` | Enable/disable the live SEO preview feature |
207
+ | `fieldOverrides` | `object` | `{}` | Customize field titles and descriptions |
208
+ | `fieldVisibility` | `object` | `{}` | Hide sitewide fields on specific post types |
209
+ | `defaultHiddenFields` | `array` | `[]` | Hide sitewide fields globally |
196
210
 
197
211
  #### Field Configuration
198
212
 
@@ -210,6 +224,50 @@ Each field in the `fieldOverrides` object can have:
210
224
  - `keywords`
211
225
  - `metaAttributes`
212
226
 
227
+ #### Field Visibility Configuration
228
+
229
+ Control which fields are visible on different content types. You can hide any SEO field on any post type:
230
+
231
+ **Available field keys:**
232
+ - `title` - Meta Title field
233
+ - `description` - Meta Description field
234
+ - `canonicalUrl` - Canonical URL field
235
+ - `metaImage` - Meta Image field
236
+ - `keywords` - Keywords field
237
+ - `metaAttributes` - Custom Meta Attributes field
238
+ - `robots` - Robots Settings field
239
+ - `openGraphSiteName` - Open Graph Site Name field (sitewide)
240
+ - `twitterSite` - X (Formerly Twitter) Site Handle field (sitewide)
241
+
242
+ **Example configurations:**
243
+
244
+ ```typescript
245
+ // Hide fields globally
246
+ seofields({
247
+ defaultHiddenFields: ['openGraphSiteName', 'twitterSite', 'keywords']
248
+ })
249
+
250
+ // Hide fields on specific content types
251
+ seofields({
252
+ fieldVisibility: {
253
+ page: {
254
+ hiddenFields: ['openGraphSiteName', 'twitterSite', 'keywords']
255
+ },
256
+ post: {
257
+ hiddenFields: ['openGraphSiteName', 'metaAttributes']
258
+ },
259
+ product: {
260
+ hiddenFields: ['canonicalUrl', 'robots']
261
+ }
262
+ }
263
+ })
264
+ ```
265
+
266
+ This is particularly useful when you want to:
267
+ - Manage sitewide settings (like site name and X handle) in a dedicated Site Settings document
268
+ - Simplify the editing experience by hiding fields that aren't relevant for certain content types
269
+ - Create different SEO workflows for different content types
270
+
213
271
  ### Field Specifications
214
272
 
215
273
  #### Meta Title
@@ -238,18 +296,18 @@ Each field in the `fieldOverrides` object can have:
238
296
  - **Best Practice**: Use the preferred URL for the page to avoid duplicate content issues
239
297
  - **Required**: Should match the actual page URL for consistency
240
298
 
241
- #### Twitter Card Image
299
+ #### X (Formerly Twitter) Card Image
242
300
 
243
301
  - **Summary Card**: Minimum 120x120px
244
302
  - **Large Image**: Minimum 280x150px
245
303
  - **Required**: Alt text for accessibility
246
304
 
247
- #### Twitter Card Creator
305
+ #### X (Formerly Twitter) Card Creator
248
306
 
249
- - **Purpose**: Attribution to content creator on Twitter
250
- - **Format**: Twitter handle with @ symbol (e.g., @creator)
307
+ - **Purpose**: Attribution to content creator on X (formerly Twitter)
308
+ - **Format**: X handle with @ symbol (e.g., @creator)
251
309
  - **Usage**: Identifies the individual author of the content
252
- - **Best Practice**: Use actual Twitter handles for proper attribution
310
+ - **Best Practice**: Use actual X handles for proper attribution
253
311
 
254
312
  ## 💻 TypeScript Usage
255
313
 
@@ -316,6 +374,8 @@ import type {
316
374
  SeoFieldsPluginConfig,
317
375
  SeoFieldConfig,
318
376
  SeoFieldKeys,
377
+ SitewideFieldKeys,
378
+ FieldVisibilityConfig,
319
379
  OpenGraphSettings,
320
380
  TwitterCardSettings,
321
381
  MetaAttribute,
@@ -325,7 +385,53 @@ import type {
325
385
  } from 'sanity-plugin-seofields'
326
386
  ```
327
387
 
328
- ## 🎯 Examples
388
+ ## 🎛️ Field Visibility Feature
389
+
390
+ The field visibility feature allows you to hide any SEO field on specific content types. This is perfect for managing sitewide settings in a dedicated Site Settings document or creating customized editing experiences for different content types.
391
+
392
+ ### Quick Example
393
+
394
+ ```typescript
395
+ // Hide specific fields on different content types
396
+ seofields({
397
+ fieldVisibility: {
398
+ page: {
399
+ hiddenFields: ['openGraphSiteName', 'twitterSite', 'keywords']
400
+ },
401
+ post: {
402
+ hiddenFields: ['openGraphSiteName', 'metaAttributes']
403
+ },
404
+ product: {
405
+ hiddenFields: ['canonicalUrl', 'robots']
406
+ }
407
+ }
408
+ })
409
+ ```
410
+
411
+ ### Site Settings Integration
412
+
413
+ Create a Site Settings document to manage sitewide fields:
414
+
415
+ ```typescript
416
+ // schemas/siteSettings.ts
417
+ export default defineType({
418
+ name: 'siteSettings',
419
+ title: 'Site Settings',
420
+ type: 'document',
421
+ fields: [
422
+ defineField({
423
+ name: 'openGraphSiteName',
424
+ title: 'Open Graph Site Name',
425
+ type: 'string',
426
+ }),
427
+ defineField({
428
+ name: 'twitterSite',
429
+ title: 'X (Formerly Twitter) Site Handle',
430
+ type: 'string',
431
+ }),
432
+ ],
433
+ })
434
+ ```
329
435
 
330
436
  ### Complete SEO Setup
331
437
 
package/dist/index.d.mts CHANGED
@@ -2,7 +2,15 @@ import {ObjectDefinition} from 'sanity'
2
2
  import {Plugin as Plugin_2} from 'sanity'
3
3
  import {PreviewConfig} from 'sanity'
4
4
 
5
+ export declare type AllFieldKeys = SeoFieldKeys | openGraphFieldKeys | twitterFieldKeys
6
+
5
7
  export declare function allSchemas(config?: SeoFieldsPluginConfig): (
8
+ | ({
9
+ type: 'object'
10
+ name: 'twitter'
11
+ } & Omit<ObjectDefinition, 'preview'> & {
12
+ preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
13
+ })
6
14
  | ({
7
15
  type: 'object'
8
16
  name: 'seoFields'
@@ -34,12 +42,6 @@ export declare function allSchemas(config?: SeoFieldsPluginConfig): (
34
42
  } & Omit<ObjectDefinition, 'preview'> & {
35
43
  preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
36
44
  })
37
- | ({
38
- type: 'object'
39
- name: 'twitter'
40
- } & Omit<ObjectDefinition, 'preview'> & {
41
- preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
42
- })
43
45
  | ({
44
46
  type: 'object'
45
47
  name: 'robots'
@@ -56,6 +58,11 @@ export declare function allSchemas(config?: SeoFieldsPluginConfig): (
56
58
 
57
59
  export declare const defaultSeoValidationRules: SeoValidationRules
58
60
 
61
+ export declare interface FieldVisibilityConfig {
62
+ hiddenFields?: AllFieldKeys[]
63
+ postType?: string
64
+ }
65
+
59
66
  export declare const isMetaAttribute: (obj: any) => obj is MetaAttribute
60
67
 
61
68
  export declare const isOpenGraphSettings: (obj: any) => obj is OpenGraphSettings
@@ -99,7 +106,17 @@ export declare const metaTagSchema: {
99
106
  preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
100
107
  }
101
108
 
102
- export declare const openGraphSchema: {
109
+ export declare type openGraphFieldKeys =
110
+ | 'openGraphUrl'
111
+ | 'openGraphTitle'
112
+ | 'openGraphDescription'
113
+ | 'openGraphSiteName'
114
+ | 'openGraphType'
115
+ | 'openGraphImageType'
116
+ | 'openGraphImage'
117
+ | 'openGraphImageUrl'
118
+
119
+ export declare function openGraphSchema(config?: SeoFieldsPluginConfig): {
103
120
  type: 'object'
104
121
  name: 'openGraph'
105
122
  } & Omit<ObjectDefinition, 'preview'> & {
@@ -113,7 +130,7 @@ export declare interface OpenGraphSettings {
113
130
  siteName?: string
114
131
  type?: 'website' | 'article' | 'profile' | 'book' | 'music' | 'video' | 'product'
115
132
  imageType?: 'upload' | 'url'
116
- image?: SanityImage
133
+ image?: SanityImageWithAlt
117
134
  imageUrl?: string
118
135
  }
119
136
 
@@ -166,6 +183,7 @@ export declare type SeoFieldKeys =
166
183
  | 'metaImage'
167
184
  | 'keywords'
168
185
  | 'metaAttributes'
186
+ | 'robots'
169
187
 
170
188
  export declare interface SeoFields {
171
189
  _type: 'seoFields'
@@ -184,10 +202,52 @@ declare const seofields: Plugin_2<void | SeoFieldsPluginConfig>
184
202
  export default seofields
185
203
 
186
204
  export declare interface SeoFieldsPluginConfig {
187
- seoPreview?: boolean
205
+ /**
206
+ * Enable or configure the SEO preview feature.
207
+ * If set to `true`, the SEO preview will be enabled with default settings.
208
+ * If set to an object, you can provide a custom prefix function to modify the URL prefix in the preview.
209
+ * The prefix function receives the current document as an argument and should return a string.
210
+ * Example:
211
+ * ```
212
+ * seoPreview: {
213
+ * prefix: (doc) => `/${doc.slug?.current || 'untitled'}`
214
+ * }
215
+ * ```
216
+ */
217
+ seoPreview?:
218
+ | boolean
219
+ | {
220
+ prefix?: (
221
+ doc: {
222
+ _type?: string
223
+ } & Record<string, unknown>,
224
+ ) => string
225
+ }
226
+ /**
227
+ * A mapping of field keys to their configuration settings.
228
+ * This allows customization of field titles and descriptions.
229
+ * For example, to change the title of the 'title' field:
230
+ */
188
231
  fieldOverrides?: {
189
- [key in SeoFieldKeys]?: SeoFieldConfig
232
+ [key in AllFieldKeys]?: SeoFieldConfig
233
+ }
234
+ /**
235
+ * A mapping of document types to field visibility configurations.
236
+ * This allows you to specify which fields should be hidden for specific document types.
237
+ */
238
+ fieldVisibility?: {
239
+ [postType: string]: FieldVisibilityConfig
190
240
  }
241
+ /**
242
+ * A list of fields that should be hidden by default in all document types.
243
+ * This can be overridden by specific document type settings in `fieldVisibility`.
244
+ */
245
+ defaultHiddenFields?: AllFieldKeys[]
246
+ /**
247
+ * The base URL of your website, used for generating full URLs in the SEO preview.
248
+ * Defaults to 'https://www.example.com' if not provided.
249
+ */
250
+ baseUrl?: string
191
251
  }
192
252
 
193
253
  export declare function seoFieldsSchema(config?: SeoFieldsPluginConfig): {
@@ -226,10 +286,22 @@ export declare interface TwitterCardSettings {
226
286
  site?: string
227
287
  title?: string
228
288
  description?: string
289
+ imageType?: 'upload' | 'url'
229
290
  image?: SanityImageWithAlt
291
+ imageUrl?: string
230
292
  }
231
293
 
232
- export declare const twitterSchema: {
294
+ export declare type twitterFieldKeys =
295
+ | 'twitterCard'
296
+ | 'twitterSite'
297
+ | 'twitterCreator'
298
+ | 'twitterTitle'
299
+ | 'twitterDescription'
300
+ | 'twitterImageType'
301
+ | 'twitterImage'
302
+ | 'twitterImageUrl'
303
+
304
+ export declare function twitterSchema(config?: SeoFieldsPluginConfig): {
233
305
  type: 'object'
234
306
  name: 'twitter'
235
307
  } & Omit<ObjectDefinition, 'preview'> & {
package/dist/index.d.ts CHANGED
@@ -2,7 +2,15 @@ import {ObjectDefinition} from 'sanity'
2
2
  import {Plugin as Plugin_2} from 'sanity'
3
3
  import {PreviewConfig} from 'sanity'
4
4
 
5
+ export declare type AllFieldKeys = SeoFieldKeys | openGraphFieldKeys | twitterFieldKeys
6
+
5
7
  export declare function allSchemas(config?: SeoFieldsPluginConfig): (
8
+ | ({
9
+ type: 'object'
10
+ name: 'twitter'
11
+ } & Omit<ObjectDefinition, 'preview'> & {
12
+ preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
13
+ })
6
14
  | ({
7
15
  type: 'object'
8
16
  name: 'seoFields'
@@ -34,12 +42,6 @@ export declare function allSchemas(config?: SeoFieldsPluginConfig): (
34
42
  } & Omit<ObjectDefinition, 'preview'> & {
35
43
  preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
36
44
  })
37
- | ({
38
- type: 'object'
39
- name: 'twitter'
40
- } & Omit<ObjectDefinition, 'preview'> & {
41
- preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
42
- })
43
45
  | ({
44
46
  type: 'object'
45
47
  name: 'robots'
@@ -56,6 +58,11 @@ export declare function allSchemas(config?: SeoFieldsPluginConfig): (
56
58
 
57
59
  export declare const defaultSeoValidationRules: SeoValidationRules
58
60
 
61
+ export declare interface FieldVisibilityConfig {
62
+ hiddenFields?: AllFieldKeys[]
63
+ postType?: string
64
+ }
65
+
59
66
  export declare const isMetaAttribute: (obj: any) => obj is MetaAttribute
60
67
 
61
68
  export declare const isOpenGraphSettings: (obj: any) => obj is OpenGraphSettings
@@ -99,7 +106,17 @@ export declare const metaTagSchema: {
99
106
  preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
100
107
  }
101
108
 
102
- export declare const openGraphSchema: {
109
+ export declare type openGraphFieldKeys =
110
+ | 'openGraphUrl'
111
+ | 'openGraphTitle'
112
+ | 'openGraphDescription'
113
+ | 'openGraphSiteName'
114
+ | 'openGraphType'
115
+ | 'openGraphImageType'
116
+ | 'openGraphImage'
117
+ | 'openGraphImageUrl'
118
+
119
+ export declare function openGraphSchema(config?: SeoFieldsPluginConfig): {
103
120
  type: 'object'
104
121
  name: 'openGraph'
105
122
  } & Omit<ObjectDefinition, 'preview'> & {
@@ -113,7 +130,7 @@ export declare interface OpenGraphSettings {
113
130
  siteName?: string
114
131
  type?: 'website' | 'article' | 'profile' | 'book' | 'music' | 'video' | 'product'
115
132
  imageType?: 'upload' | 'url'
116
- image?: SanityImage
133
+ image?: SanityImageWithAlt
117
134
  imageUrl?: string
118
135
  }
119
136
 
@@ -166,6 +183,7 @@ export declare type SeoFieldKeys =
166
183
  | 'metaImage'
167
184
  | 'keywords'
168
185
  | 'metaAttributes'
186
+ | 'robots'
169
187
 
170
188
  export declare interface SeoFields {
171
189
  _type: 'seoFields'
@@ -184,10 +202,52 @@ declare const seofields: Plugin_2<void | SeoFieldsPluginConfig>
184
202
  export default seofields
185
203
 
186
204
  export declare interface SeoFieldsPluginConfig {
187
- seoPreview?: boolean
205
+ /**
206
+ * Enable or configure the SEO preview feature.
207
+ * If set to `true`, the SEO preview will be enabled with default settings.
208
+ * If set to an object, you can provide a custom prefix function to modify the URL prefix in the preview.
209
+ * The prefix function receives the current document as an argument and should return a string.
210
+ * Example:
211
+ * ```
212
+ * seoPreview: {
213
+ * prefix: (doc) => `/${doc.slug?.current || 'untitled'}`
214
+ * }
215
+ * ```
216
+ */
217
+ seoPreview?:
218
+ | boolean
219
+ | {
220
+ prefix?: (
221
+ doc: {
222
+ _type?: string
223
+ } & Record<string, unknown>,
224
+ ) => string
225
+ }
226
+ /**
227
+ * A mapping of field keys to their configuration settings.
228
+ * This allows customization of field titles and descriptions.
229
+ * For example, to change the title of the 'title' field:
230
+ */
188
231
  fieldOverrides?: {
189
- [key in SeoFieldKeys]?: SeoFieldConfig
232
+ [key in AllFieldKeys]?: SeoFieldConfig
233
+ }
234
+ /**
235
+ * A mapping of document types to field visibility configurations.
236
+ * This allows you to specify which fields should be hidden for specific document types.
237
+ */
238
+ fieldVisibility?: {
239
+ [postType: string]: FieldVisibilityConfig
190
240
  }
241
+ /**
242
+ * A list of fields that should be hidden by default in all document types.
243
+ * This can be overridden by specific document type settings in `fieldVisibility`.
244
+ */
245
+ defaultHiddenFields?: AllFieldKeys[]
246
+ /**
247
+ * The base URL of your website, used for generating full URLs in the SEO preview.
248
+ * Defaults to 'https://www.example.com' if not provided.
249
+ */
250
+ baseUrl?: string
191
251
  }
192
252
 
193
253
  export declare function seoFieldsSchema(config?: SeoFieldsPluginConfig): {
@@ -226,10 +286,22 @@ export declare interface TwitterCardSettings {
226
286
  site?: string
227
287
  title?: string
228
288
  description?: string
289
+ imageType?: 'upload' | 'url'
229
290
  image?: SanityImageWithAlt
291
+ imageUrl?: string
230
292
  }
231
293
 
232
- export declare const twitterSchema: {
294
+ export declare type twitterFieldKeys =
295
+ | 'twitterCard'
296
+ | 'twitterSite'
297
+ | 'twitterCreator'
298
+ | 'twitterTitle'
299
+ | 'twitterDescription'
300
+ | 'twitterImageType'
301
+ | 'twitterImage'
302
+ | 'twitterImageUrl'
303
+
304
+ export declare function twitterSchema(config?: SeoFieldsPluginConfig): {
233
305
  type: 'object'
234
306
  name: 'twitter'
235
307
  } & Omit<ObjectDefinition, 'preview'> & {