Desk Structure Pane
Embed the SEO Health Dashboard directly inside the Structure tool using createSeoHealthPane(S, options) — clicking any document row opens the document editor as a split pane to the right.
Import
import { createSeoHealthPane } from 'sanity-plugin-seofields'Do NOT wrap in S.component()
createSeoHealthPane already calls S.component() internally and returns a ComponentBuilder. Wrapping it again in S.component(...) causes: "component is required for component structure item".
Usage
Pass Sanity's S as the first argument and your options as the second. Use the result directly as the .child() value — no S.component() wrapper.
// sanity.config.ts
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import seofields, { createSeoHealthPane } from 'sanity-plugin-seofields'
export default defineConfig({
plugins: [
seofields({ healthDashboard: false }), // optional: hide the top-level tool tab
structureTool({
structure: (S) =>
S.list()
.title('Content')
.items([
S.documentTypeListItem('post').title('Posts'),
S.divider(),
S.listItem()
.title('SEO Health')
.child(
createSeoHealthPane(S, {
licenseKey: 'SEOF-XXXX-XXXX-XXXX',
query: `*[_type == "post" && defined(seo)]{
_id, _type, title, slug, seo, _updatedAt
}`,
title: 'Posts SEO Health',
})
),
]),
}),
],
})Options
Both arguments are required. options accepts all SeoHealthDashboard props plus the fields below.
| Option | Type | Default | Description |
|---|---|---|---|
| licenseKeyrequired | string | — | License key (format: SEOF-XXXX-XXXX-XXXX). The pane will not render without a valid key. |
| query | string | — | GROQ query for customQuery. Must return _id, _type, title, seo, _updatedAt. |
| title | string | 'SEO Health' | Pane title shown in the structure breadcrumb. |
| openInPane | boolean | true | Enable row links that open the document editor as a pane to the right. |
| ...rest | SeoHealthDashboardProps | — | All other dashboard props (typeLabels, typeColumnMode, titleField, docBadge, etc.). |
How split-pane navigation works
Each document row title is wrapped with usePaneRouter().ChildLink from sanity/structure. When clicked, it appends a new pane segment to the Studio URL. The built-in .child() resolver intercepts that segment and renders S.document().documentId(docId).schemaType(type). The document _type flows from the row via childParameters so schemaType is always correct.
Was this page helpful?