Skip to main content
seofields

Use case

Use Sanity SEO fields in Next.js metadata

Query seoFields from Sanity, return buildSeoMeta() from generateMetadata(), render Schema.org JSON-LD components in Server Components, and keep frontend metadata tied to editor-owned content.

Benefits

Works with App Router

Return a Next.js Metadata-compatible object from generateMetadata() using buildSeoMeta().

Keeps editors in control

Sanity owns title, description, canonical URL, social cards, robots, and structured data fields.

Not locked to one frontend

Next.js uses the /next helper, while Astro, Nuxt, Vue, SvelteKit, Remix, and custom renderers can use /head.

How it works in Sanity

1

Query the document

Fetch slug, content, and the nested seo object with GROQ in your route.

2

Return metadata

Pass the seo object to buildSeoMeta() with baseUrl, path, defaults, and an image resolver.

3

Render JSON-LD

Use Schema.org components or builders alongside your page content when structured data is present.

Code examples

app/blog/[slug]/page.tsx
import type { Metadata } from 'next'
import { buildSeoMeta } from 'sanity-plugin-seofields/next'

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>
}): Promise<Metadata> {
  const { slug } = await params
  const post = await getPost(slug)

  return buildSeoMeta({
    seo: post?.seo,
    baseUrl: 'https://example.com',
    path: `/blog/${slug}`,
    defaults: {
      title: post?.title,
      siteName: 'Example',
      twitterSite: '@example',
    },
    imageUrlResolver: (image) => image.asset?.url,
  })
}
GROQ query
*[_type == "post" && slug.current == $slug][0]{
  title,
  "slug": slug.current,
  seo {
    title,
    description,
    canonicalUrl,
    keywords,
    robots { noIndex, noFollow },
    openGraph { title, description, type, imageType, image { asset-> { url } }, imageUrl },
    twitter { card, title, description, imageType, image { asset-> { url } }, imageUrl },
    hreflangs[] { language, region, url }
  },
  schemaOrgArticle
}
Other frontend frameworks
import { buildSeoHead } from 'sanity-plugin-seofields/head'

const head = buildSeoHead({
  seo: page.seo,
  baseUrl: 'https://example.com',
  path: page.path,
})

// Use this shape in Astro, Nuxt, Vue, SvelteKit, Remix,
// or any renderer that wants serializable head data.

FAQ

Does buildSeoMeta work in Server Components?

Yes. The /next entry point is designed for Next.js App Router and can be used from generateMetadata() and Server Component code.

Can I still use the plugin outside Next.js?

Yes. Use sanity-plugin-seofields/head when you need plain head data for Astro, Nuxt, Vue, SvelteKit, Remix, or a custom renderer.

How do image URLs get resolved?

Pass an imageUrlResolver to buildSeoMeta() so Sanity image references can become absolute image URLs.

Can I render Schema.org JSON-LD in Next.js?

Yes. The /next export includes Schema.org React components and JSON-LD builder helpers for individual schema types.

Wire Sanity SEO into Next.js

Use the frontend integration docs for complete App Router, Pages Router, and framework-neutral examples.