Sanity + Next.js SEO plugin similar to WordPress Yoast - setup help needed
The SEO Pane plugin is exactly what you're looking for β it brings Yoast-style SEO analysis directly into Sanity Studio. Here's what you need to know to get it working with Next.js:
Installation and Setup
Install the plugin in your Sanity Studio project:
npm install sanity-plugin-seo-paneThe plugin works as a View Pane in your Studio's Structure Builder. You'll need to configure it in your desk structure to specify where your SEO fields live and how to preview your front-end:
// ./src/deskStructure.js (or sanity.config.ts)
import { SEOPane } from 'sanity-plugin-seo-pane'
S.view
.component(SEOPane)
.options({
keywords: `seo.keywords`, // dot-notated path to your keywords field
synonyms: `seo.synonyms`, // path to synonyms field
url: (doc) => resolveProductionUrl(doc), // function that returns preview URL
})
.title('SEO')Key Setup Requirements
1. Preview URL Configuration
The plugin needs to fetch your rendered front-end to analyze it. The url function should return the preview URL for your document β similar to what you'd use for Live Preview.
2. Handle CORS Issues
Since the plugin fetches your Next.js site from the Studio, you'll need to handle CORS in your preview API route:
// pages/api/preview.js
const corsOrigin = process.env.NODE_ENV === 'development'
? `http://localhost:3333`
: `https://your-studio.sanity.studio`
res.setHeader('Access-Control-Allow-Origin', corsOrigin)
res.setHeader('Access-Control-Allow-Credentials', true)3. Return HTML for Analysis
The plugin appends ?fetch=true to preview URLs. Your preview route should detect this and return the page HTML as a string instead of redirecting:
// pages/api/preview.js
if (req?.query?.fetch === 'true') {
const proto = process.env.NODE_ENV === 'development' ? `http://` : `https://`
const host = req.headers.host
const pathname = req?.query?.slug ?? `/`
const absoluteUrl = new URL(`${proto}${host}${pathname}`).toString()
const previewHtml = await fetch(absoluteUrl, {
credentials: `include`,
headers: {Cookie: req.headers.cookie},
})
.then((previewRes) => previewRes.text())
.catch((err) => console.error(err))
return res.send(previewHtml)
}4. Mark Your Content Area
The plugin looks for content in your HTML. Add this attribute to your main content container:
<div data-content="main">
<!-- Your main content here -->
</div>Or use a standard <main> tag as a fallback.
5. Add Canonical URL
Include a canonical tag in your page head for proper URL detection:
<link rel="canonical" href="https://example.com/your-page" />Compatibility Notes for Next.js
For Next.js 13+ with App Router / Vite:
You may need to add polyfills for Node.js built-ins that the underlying yoastseo package requires:
// sanity.cli.ts
import {nodePolyfills} from 'vite-plugin-node-polyfills'
export default defineCliConfig({
vite: (prev) => ({
...prev,
plugins: [
...prev.plugins,
nodePolyfills({ util: true }),
],
define: {
...prev.define,
'process.env': {},
},
}),
})For embedded Studio in Next.js:
Update your next.config.mjs:
const config = {
experimental: {
esmExternals: 'loose'
},
}What You Get
Once configured, you'll see real-time Yoast-style analysis as you edit your content, including:
- Keyword density analysis
- Content readability scores
- SEO problems and suggestions
- Live preview of how your content will appear
The plugin is maintained by Simeon Griggs from Sanity's team, and there's a detailed blog post walking through its features. The GitHub repo has full documentation and examples.
This should give you the Yoast-like experience you're looking for! The key is getting the preview URL and CORS configuration right so the plugin can analyze your rendered pages.
Show original thread7 replies
Sanity β Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.