sanity-plugin-seofields 1.2.0 → 1.2.2
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 +60 -0
- package/dist/index.d.mts +80 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +269 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +269 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/SeoHealthDashboard.tsx +322 -21
- package/src/components/SeoHealthPane.tsx +81 -0
- package/src/index.ts +2 -0
- package/src/plugin.ts +13 -0
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ A comprehensive Sanity Studio v3 plugin to manage SEO fields like meta titles, d
|
|
|
21
21
|
- ✅ **Validation**: Built-in character limits and best practices
|
|
22
22
|
- 🎛️ **Field Visibility**: Hide sitewide fields on specific content types
|
|
23
23
|
- 📊 **SEO Health Dashboard**: Studio-wide overview of SEO completeness with scores, issue highlights, and direct document links
|
|
24
|
+
- 🗂️ **Desk Structure Pane**: Embed the dashboard inside the Structure tool with `createSeoHealthPane` — supports split-pane document editing
|
|
24
25
|
|
|
25
26
|
## 📦 Installation
|
|
26
27
|
|
|
@@ -531,6 +532,65 @@ seofields({
|
|
|
531
532
|
|
|
532
533
|
> **Scoring logic:** each field earns its full points when a non-empty value is present, zero when missing. `query.groq` lets you control exactly which documents are included in the audit.
|
|
533
534
|
|
|
535
|
+
## 🗂️ Desk Structure Pane
|
|
536
|
+
|
|
537
|
+
Embed the SEO Health Dashboard **directly inside the Structure tool** as a pane with split-pane document editing — clicking any row opens the document editor to the right.
|
|
538
|
+
|
|
539
|
+
### Import
|
|
540
|
+
|
|
541
|
+
```typescript
|
|
542
|
+
import {createSeoHealthPane} from 'sanity-plugin-seofields'
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Usage
|
|
546
|
+
|
|
547
|
+
`createSeoHealthPane(S, options)` requires both arguments: Sanity's structure builder `S` and an options object with a required `licenseKey`. It returns a **`ComponentBuilder`** — use it **directly** as the `.child()` value.
|
|
548
|
+
|
|
549
|
+
> ⚠️ **Do NOT wrap in `S.component()`.** The function already calls `S.component()` internally. Wrapping it again causes: _"component is required for component structure item"_.
|
|
550
|
+
|
|
551
|
+
```typescript
|
|
552
|
+
// sanity.config.ts
|
|
553
|
+
import {defineConfig} from 'sanity'
|
|
554
|
+
import {structureTool} from 'sanity/structure'
|
|
555
|
+
import seofields, {createSeoHealthPane} from 'sanity-plugin-seofields'
|
|
556
|
+
|
|
557
|
+
export default defineConfig({
|
|
558
|
+
plugins: [
|
|
559
|
+
seofields({healthDashboard: false}), // optional: hide the top-level tool tab
|
|
560
|
+
structureTool({
|
|
561
|
+
structure: (S) =>
|
|
562
|
+
S.list()
|
|
563
|
+
.title('Content')
|
|
564
|
+
.items([
|
|
565
|
+
S.documentTypeListItem('post').title('Posts'),
|
|
566
|
+
S.divider(),
|
|
567
|
+
S.listItem()
|
|
568
|
+
.title('SEO Health')
|
|
569
|
+
.child(
|
|
570
|
+
createSeoHealthPane(S, {
|
|
571
|
+
licenseKey: 'SEOF-XXXX-XXXX-XXXX',
|
|
572
|
+
query: `*[_type == "post" && defined(seo)]{
|
|
573
|
+
_id, _type, title, slug, seo, _updatedAt
|
|
574
|
+
}`,
|
|
575
|
+
title: 'Posts SEO Health',
|
|
576
|
+
}),
|
|
577
|
+
),
|
|
578
|
+
]),
|
|
579
|
+
}),
|
|
580
|
+
],
|
|
581
|
+
})
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### `createSeoHealthPane` options
|
|
585
|
+
|
|
586
|
+
| Option | Type | Default | Description |
|
|
587
|
+
| ------------ | --------- | -------------- | --------------------------------------------------------------------- |
|
|
588
|
+
| `licenseKey` | `string` | **required** | License key (format `SEOF-XXXX-XXXX-XXXX`). |
|
|
589
|
+
| `query` | `string` | — | GROQ query. Must return `_id`, `_type`, `title`, `seo`, `_updatedAt`. |
|
|
590
|
+
| `title` | `string` | `'SEO Health'` | Pane title shown in breadcrumb |
|
|
591
|
+
| `openInPane` | `boolean` | `true` | Enable row links that open the document editor as a pane to the right. |
|
|
592
|
+
| `...rest` | — | — | All other `SeoHealthDashboardProps` |
|
|
593
|
+
|
|
534
594
|
## 🌐 Frontend Integration
|
|
535
595
|
|
|
536
596
|
### Next.js Example
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,44 @@
|
|
|
1
|
+
import type {ComponentBuilder} from 'sanity/structure'
|
|
1
2
|
import {JSX} from 'react'
|
|
2
3
|
import {ObjectDefinition} from 'sanity'
|
|
3
4
|
import {Plugin as Plugin_2} from 'sanity'
|
|
4
5
|
import {PreviewConfig} from 'sanity'
|
|
5
6
|
import {default as React_2} from 'react'
|
|
6
7
|
import {SchemaTypeDefinition} from 'sanity'
|
|
8
|
+
import type {StructureBuilder} from 'sanity/structure'
|
|
7
9
|
|
|
8
10
|
export declare type AllFieldKeys = SeoFieldKeys | openGraphFieldKeys | twitterFieldKeys
|
|
9
11
|
|
|
10
12
|
export declare function allSchemas(config?: SeoFieldsPluginConfig): SchemaTypeDefinition[]
|
|
11
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Creates a desk-structure pane for the SEO Health Dashboard.
|
|
16
|
+
*
|
|
17
|
+
* Returns a **`ComponentBuilder`** with a built-in `.child()` resolver so that
|
|
18
|
+
* clicking any document row opens the document editor as a split pane to the right.
|
|
19
|
+
*
|
|
20
|
+
* Use it **directly** as the `.child()` value — do **not** wrap it in `S.component()`.
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* // sanity.config.ts
|
|
24
|
+
* structure: (S) =>
|
|
25
|
+
* S.list().items([
|
|
26
|
+
* S.listItem()
|
|
27
|
+
* .title('SEO Health')
|
|
28
|
+
* .child(
|
|
29
|
+
* createSeoHealthPane(S, {
|
|
30
|
+
* licenseKey: 'SEOF-XXXX-XXXX-XXXX',
|
|
31
|
+
* query: `*[_type == "post" && defined(seo)]{ _id, _type, title, slug, seo, _updatedAt }`,
|
|
32
|
+
* })
|
|
33
|
+
* ),
|
|
34
|
+
* ])
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function createSeoHealthPane(
|
|
38
|
+
optionsOrS: StructureBuilder,
|
|
39
|
+
optionsWhenS: SeoHealthPaneOptions,
|
|
40
|
+
): ComponentBuilder
|
|
41
|
+
|
|
12
42
|
export declare interface DocumentWithSeoHealth {
|
|
13
43
|
_id: string
|
|
14
44
|
_type: string
|
|
@@ -308,6 +338,16 @@ export declare interface SeoFieldsPluginConfig {
|
|
|
308
338
|
fontSize?: string
|
|
309
339
|
}
|
|
310
340
|
| undefined
|
|
341
|
+
/**
|
|
342
|
+
* Enable preview/demo mode to show dummy data.
|
|
343
|
+
* Useful for testing, documentation, or showcasing the dashboard.
|
|
344
|
+
* When enabled, displays realistic sample documents with various SEO scores.
|
|
345
|
+
* Defaults to `false`.
|
|
346
|
+
*
|
|
347
|
+
* @example
|
|
348
|
+
* previewMode: true
|
|
349
|
+
*/
|
|
350
|
+
previewMode?: boolean
|
|
311
351
|
}
|
|
312
352
|
}
|
|
313
353
|
|
|
@@ -413,6 +453,25 @@ declare interface SeoHealthDashboardProps {
|
|
|
413
453
|
* Defaults to `"No documents found"`.
|
|
414
454
|
*/
|
|
415
455
|
noDocuments?: React_2.ReactNode
|
|
456
|
+
/**
|
|
457
|
+
* Enable preview/demo mode to show dummy data.
|
|
458
|
+
* Useful for testing, documentation, or showcasing the dashboard.
|
|
459
|
+
* When enabled, displays realistic sample documents with various SEO scores.
|
|
460
|
+
* Defaults to `false`.
|
|
461
|
+
*/
|
|
462
|
+
previewMode?: boolean
|
|
463
|
+
/**
|
|
464
|
+
* When `true`, clicking a document title opens the document editor as a split
|
|
465
|
+
* pane to the right, keeping the SEO Health pane visible on the left.
|
|
466
|
+
* This uses Sanity's pane router and requires the component to be rendered
|
|
467
|
+
* inside a desk-structure pane context (i.e. via `createSeoHealthPane`).
|
|
468
|
+
*
|
|
469
|
+
* When `false` (default), clicking navigates to the document via the standard
|
|
470
|
+
* intent-link system (full navigation).
|
|
471
|
+
*
|
|
472
|
+
* This is set to `true` automatically by `createSeoHealthPane`.
|
|
473
|
+
*/
|
|
474
|
+
openInPane?: boolean
|
|
416
475
|
}
|
|
417
476
|
|
|
418
477
|
export declare interface SeoHealthMetrics {
|
|
@@ -421,6 +480,27 @@ export declare interface SeoHealthMetrics {
|
|
|
421
480
|
issues: string[]
|
|
422
481
|
}
|
|
423
482
|
|
|
483
|
+
/**
|
|
484
|
+
* Options accepted by `createSeoHealthPane`.
|
|
485
|
+
* All props from `SeoHealthDashboardProps` are supported.
|
|
486
|
+
*
|
|
487
|
+
* `licenseKey` is **required** — the dashboard will not render without it.
|
|
488
|
+
*/
|
|
489
|
+
export declare interface SeoHealthPaneOptions extends Omit<SeoHealthDashboardProps, 'customQuery'> {
|
|
490
|
+
/** Required license key (format: `SEOF-XXXX-XXXX-XXXX`). */
|
|
491
|
+
licenseKey: string
|
|
492
|
+
/**
|
|
493
|
+
* A fully custom GROQ query used to fetch documents for the dashboard.
|
|
494
|
+
* The query must return documents with at least: `_id`, `_type`, `title`, `seo`, `_updatedAt`.
|
|
495
|
+
*
|
|
496
|
+
* Takes precedence over `queryTypes` when both are provided.
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* query: `*[_type in ["post","page"] && defined(seo)]{ _id, _type, title, slug, seo, _updatedAt }`
|
|
500
|
+
*/
|
|
501
|
+
query?: string
|
|
502
|
+
}
|
|
503
|
+
|
|
424
504
|
export declare type SeoHealthStatus = 'excellent' | 'good' | 'fair' | 'poor' | 'missing'
|
|
425
505
|
|
|
426
506
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,44 @@
|
|
|
1
|
+
import type {ComponentBuilder} from 'sanity/structure'
|
|
1
2
|
import {JSX} from 'react'
|
|
2
3
|
import {ObjectDefinition} from 'sanity'
|
|
3
4
|
import {Plugin as Plugin_2} from 'sanity'
|
|
4
5
|
import {PreviewConfig} from 'sanity'
|
|
5
6
|
import {default as React_2} from 'react'
|
|
6
7
|
import {SchemaTypeDefinition} from 'sanity'
|
|
8
|
+
import type {StructureBuilder} from 'sanity/structure'
|
|
7
9
|
|
|
8
10
|
export declare type AllFieldKeys = SeoFieldKeys | openGraphFieldKeys | twitterFieldKeys
|
|
9
11
|
|
|
10
12
|
export declare function allSchemas(config?: SeoFieldsPluginConfig): SchemaTypeDefinition[]
|
|
11
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Creates a desk-structure pane for the SEO Health Dashboard.
|
|
16
|
+
*
|
|
17
|
+
* Returns a **`ComponentBuilder`** with a built-in `.child()` resolver so that
|
|
18
|
+
* clicking any document row opens the document editor as a split pane to the right.
|
|
19
|
+
*
|
|
20
|
+
* Use it **directly** as the `.child()` value — do **not** wrap it in `S.component()`.
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* // sanity.config.ts
|
|
24
|
+
* structure: (S) =>
|
|
25
|
+
* S.list().items([
|
|
26
|
+
* S.listItem()
|
|
27
|
+
* .title('SEO Health')
|
|
28
|
+
* .child(
|
|
29
|
+
* createSeoHealthPane(S, {
|
|
30
|
+
* licenseKey: 'SEOF-XXXX-XXXX-XXXX',
|
|
31
|
+
* query: `*[_type == "post" && defined(seo)]{ _id, _type, title, slug, seo, _updatedAt }`,
|
|
32
|
+
* })
|
|
33
|
+
* ),
|
|
34
|
+
* ])
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function createSeoHealthPane(
|
|
38
|
+
optionsOrS: StructureBuilder,
|
|
39
|
+
optionsWhenS: SeoHealthPaneOptions,
|
|
40
|
+
): ComponentBuilder
|
|
41
|
+
|
|
12
42
|
export declare interface DocumentWithSeoHealth {
|
|
13
43
|
_id: string
|
|
14
44
|
_type: string
|
|
@@ -308,6 +338,16 @@ export declare interface SeoFieldsPluginConfig {
|
|
|
308
338
|
fontSize?: string
|
|
309
339
|
}
|
|
310
340
|
| undefined
|
|
341
|
+
/**
|
|
342
|
+
* Enable preview/demo mode to show dummy data.
|
|
343
|
+
* Useful for testing, documentation, or showcasing the dashboard.
|
|
344
|
+
* When enabled, displays realistic sample documents with various SEO scores.
|
|
345
|
+
* Defaults to `false`.
|
|
346
|
+
*
|
|
347
|
+
* @example
|
|
348
|
+
* previewMode: true
|
|
349
|
+
*/
|
|
350
|
+
previewMode?: boolean
|
|
311
351
|
}
|
|
312
352
|
}
|
|
313
353
|
|
|
@@ -413,6 +453,25 @@ declare interface SeoHealthDashboardProps {
|
|
|
413
453
|
* Defaults to `"No documents found"`.
|
|
414
454
|
*/
|
|
415
455
|
noDocuments?: React_2.ReactNode
|
|
456
|
+
/**
|
|
457
|
+
* Enable preview/demo mode to show dummy data.
|
|
458
|
+
* Useful for testing, documentation, or showcasing the dashboard.
|
|
459
|
+
* When enabled, displays realistic sample documents with various SEO scores.
|
|
460
|
+
* Defaults to `false`.
|
|
461
|
+
*/
|
|
462
|
+
previewMode?: boolean
|
|
463
|
+
/**
|
|
464
|
+
* When `true`, clicking a document title opens the document editor as a split
|
|
465
|
+
* pane to the right, keeping the SEO Health pane visible on the left.
|
|
466
|
+
* This uses Sanity's pane router and requires the component to be rendered
|
|
467
|
+
* inside a desk-structure pane context (i.e. via `createSeoHealthPane`).
|
|
468
|
+
*
|
|
469
|
+
* When `false` (default), clicking navigates to the document via the standard
|
|
470
|
+
* intent-link system (full navigation).
|
|
471
|
+
*
|
|
472
|
+
* This is set to `true` automatically by `createSeoHealthPane`.
|
|
473
|
+
*/
|
|
474
|
+
openInPane?: boolean
|
|
416
475
|
}
|
|
417
476
|
|
|
418
477
|
export declare interface SeoHealthMetrics {
|
|
@@ -421,6 +480,27 @@ export declare interface SeoHealthMetrics {
|
|
|
421
480
|
issues: string[]
|
|
422
481
|
}
|
|
423
482
|
|
|
483
|
+
/**
|
|
484
|
+
* Options accepted by `createSeoHealthPane`.
|
|
485
|
+
* All props from `SeoHealthDashboardProps` are supported.
|
|
486
|
+
*
|
|
487
|
+
* `licenseKey` is **required** — the dashboard will not render without it.
|
|
488
|
+
*/
|
|
489
|
+
export declare interface SeoHealthPaneOptions extends Omit<SeoHealthDashboardProps, 'customQuery'> {
|
|
490
|
+
/** Required license key (format: `SEOF-XXXX-XXXX-XXXX`). */
|
|
491
|
+
licenseKey: string
|
|
492
|
+
/**
|
|
493
|
+
* A fully custom GROQ query used to fetch documents for the dashboard.
|
|
494
|
+
* The query must return documents with at least: `_id`, `_type`, `title`, `seo`, `_updatedAt`.
|
|
495
|
+
*
|
|
496
|
+
* Takes precedence over `queryTypes` when both are provided.
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* query: `*[_type in ["post","page"] && defined(seo)]{ _id, _type, title, slug, seo, _updatedAt }`
|
|
500
|
+
*/
|
|
501
|
+
query?: string
|
|
502
|
+
}
|
|
503
|
+
|
|
424
504
|
export declare type SeoHealthStatus = 'excellent' | 'good' | 'fair' | 'poor' | 'missing'
|
|
425
505
|
|
|
426
506
|
/**
|