API Reference
@better-seo/core
Zero runtime dependency — pure transforms.
Model
| Symbol |
Description |
createSEO(input, config) |
Normalize + fallbacks → canonical SEO |
mergeSEO(parent, child, config?) |
Layout + page composition, deterministic merge |
withSEO(parent, child, config?) |
Alias: mergeSEO + adapter output |
Schema Helpers
| Helper |
Sets |
webPage(parts) |
@type: "WebPage" |
article(parts) |
@type: "Article" |
techArticle(parts) |
@type: "TechArticle" |
organization(parts) |
@type: "Organization" |
person(parts) |
@type: "Person" |
product(parts) |
@type: "Product" |
breadcrumbList(parts) |
@type: "BreadcrumbList" |
faqPage(parts) |
@type: "FAQPage" |
customSchema(node) |
Escape hatch for any schema.org type |
JSON-LD / Tags
| Symbol |
Description |
serializeJSONLD(graph) |
HTML-safe JSON for <script> embedding |
renderTags(seo, config?) |
Vanilla TagDescriptor[] for non-framework use |
Validation (Dev)
| Symbol |
Description |
validateSEO(seo, opts?) |
Dev warnings: title length, missing description, OG image dimensions |
Options: requireDescription (error if missing),
titleMaxLength (default 60), descriptionMaxLength (default 165).
Returns [] in production.
Rules
| Symbol |
Description |
applyRules(route, rules) |
Pure: glob match → merge partial SEO |
createSEOForRoute(route, input, config) |
Apply rules + createSEO in one call |
Context / Globals
| Symbol |
Description |
createSEOContext(config) |
Request-scoped config (Edge/multi-tenant safe) |
initSEO(config) |
Global default (Node only — avoid for SSR) |
registerAdapter(id, impl) |
Register framework adapter |
getAdapter(id) |
Get registered adapter |
Plugins
| Hook |
When |
Use Case |
beforeMerge |
Rules + layout + page merged |
Strip tracking params, normalize URLs |
afterMerge |
Final SEO before adapter |
Enforce tenant @id, locale fallbacks |
onRenderTags |
Vanilla render path |
Extra <link>, dns-prefetch, preconnect |
Migration / Content
| Symbol |
Description |
fromNextSeo(props) |
Map next-seo DefaultSeo props → SEOInput |
fromContent(title, body?) |
Infer SEOInput from string (no parsers in core) |
fromMdxString(mdx) |
Alias for fromContent with MDX import stripping |
Node-Only Export
Import from @better-seo/core/node (never in Edge bundles):
| Symbol |
Description |
readPackageJsonForSEO() |
Read name, homepage, description from package.json |
inferSEOConfigFromEnvAndPackageJson() |
Build SEOConfig from env vars + package hints |
initSEOFromPackageJson() |
Infer + initSEO (global — prefer createSEOContext) |
@better-seo/next
| Symbol |
Description |
seo(input, config?) |
Voilà shorthand → Metadata export |
prepareNextSeo(input, config) |
Full config + SEO for NextJsonLd |
withSEO(parent, child, config?) |
Layered metadata |
seoRoute(route, input, config) |
Apply rules + prepareNextSeo |
seoLayout(input, config) |
Layout-level SEO |
seoPage(input, config?) |
Page-level SEO |
JSON-LD: import NextJsonLd from
@better-seo/next/json-ld.
@better-seo/react
| Symbol |
Description |
BetterSEOHelmet |
Drop-in Helmet wrapper |
toHelmetProps(seo) |
Map SEO → Helmet props |
SEOProvider |
Context provider for useSEO |
useSEO() |
Hook — must be inside SEOProvider |