Framework Adapters

One SEO document model, multiple framework outputs. Every adapter implements:

interface SEOAdapter<TOutput> {
  id: string
  toFramework(seo: SEO): TOutput
}

Adapter Matrix

Framework Package Output Status
Next.js (App Router) @better-seo/next Metadata ✅ Shipped
Next.js (Pages Router) @better-seo/next <NextSeo /> patterns ✅ Documented
React (SPA / Vite) @better-seo/react Helmet props ✅ Shipped
Remix @better-seo/remix meta / links Planned
Astro @better-seo/astro Frontmatter Planned
Nuxt @better-seo/nuxt useHead bridge Planned
Vanilla @better-seo/core renderTags() ✅ Shipped

Explicit Registration (Production)

import { registerAdapter, seoForFramework } from "@better-seo/core"
import { adapter as nextAdapter } from "@better-seo/next"

registerAdapter("next", nextAdapter)
const metadata = seoForFramework("next", { title: "Home" })

Auto-Registration (Dev Convenience)

import { seo } from "@better-seo/next" // self-registers
export const metadata = seo({ title: "Home" })

Vanilla / Non-Framework

import { createSEO, renderTags } from "@better-seo/core"
const seo = createSEO({ title: "Home" }, config)
const tags = renderTags(seo)
// → [{ kind: "meta", name: "title", content: "Home" }, ...]

Building a Custom Adapter

import type { SEOAdapter, SEO } from "@better-seo/core"

const myAdapter: SEOAdapter<string> = {
  id: "my-framework",
  toFramework(seo: SEO): string {
    return generateHeadTags(seo)
  },
}

registerAdapter("my-framework", myAdapter)

See Adding frameworks for the full guide.