@moonsio/next-schema
v0.16.0
Published
A comprehensive Schema.org JSON‑LD solution for React/Next.js apps. Strongly typed, composable schemas, and a single `SchemaJson` component that outputs a valid `<script type="application/ld+json">` tag.
Readme
@moonsio/next-schema
A comprehensive Schema.org JSON‑LD solution for React/Next.js apps. Strongly typed, composable schemas, and a single SchemaJson component that outputs a valid <script type="application/ld+json"> tag.
Features
- TypeScript-first: rich types for all supported entities
- Composable: supply only the entities you need; we build a single
@graph - Stable IDs: IDs are generated consistently using a configurable base URL
- Next.js ready: safe to use in App Router or Pages Router (SSR compatible)
- React 18 and 19: published with peer ranges
^18 || ^19
Installation
pnpm add @moonsio/next-schema
# or
npm i @moonsio/next-schemaPeer dependencies you must have in your app:
{
"peerDependencies": {
"react": "^18 || ^19",
"react-dom": "^18 || ^19"
}
}Quick start
- Configure the base URL once at app startup (used to build stable
@ids):
// e.g. app/layout.tsx or pages/_app.tsx
import { setBaseUrl } from '@moonsio/next-schema'
setBaseUrl('https://example.com')- Render
SchemaJsonon any page. Only pass what you need; we will include the matching entities in@graph.
import { SchemaJson } from '@moonsio/next-schema'
export default function HomePage() {
return (
<SchemaJson
logo={{
image: { srcUrl: 'https://example.com/logo.png', width: 512, height: 512 },
url: 'https://example.com'
}}
website={{ baseUrl: 'https://example.com', companyName: 'Example Inc.' }}
webpage={{ name: 'Home', description: 'Welcome', slug: '' }}
/>
)
}Supported entities
Pass any of the following props to SchemaJson; if provided, a corresponding node will be added to @graph:
addressarticlebreadcrumbbookdataseteducationalOrganizationeventfaqPagehowTologo(recommended)medicalConditionmedicalOrganizationmovienewsArticleorganizationpersonplaceproductrestaurantsoftwareApplicationvideoObjectwebpage(recommended)website(recommended)
Examples
Article
<SchemaJson
logo={{ image:{ srcUrl:'/logo.png', width:512, height:512 }, url:'https://example.com' }}
website={{ baseUrl:'https://example.com', companyName:'Example Inc.' }}
webpage={{ name:'My Article', description:'...', slug:'blog/my-article' }}
article={{
headline: 'My Article',
articleTitle: 'My Article',
description: 'Short description',
slug: 'blog/my-article',
author: 'Person',
datePublished: new Date(),
}}
/>Product
<SchemaJson
logo={{ image:{ srcUrl:'/logo.png', width:512, height:512 }, url:'https://example.com' }}
website={{ baseUrl:'https://example.com', companyName:'Example Inc.' }}
webpage={{ name:'Product', description:'...', slug:'products/widget' }}
product={{
name: 'Widget',
description: 'A great widget',
sku: 'WID-001',
offers: { price: 19.99, priceCurrency: 'USD' },
url: 'products/widget'
}}
/>Event (virtual or physical)
<SchemaJson
logo={{ image:{ srcUrl:'/logo.png', width:512, height:512 }, url:'https://example.com' }}
website={{ baseUrl:'https://example.com', companyName:'Example Inc.' }}
webpage={{ name:'Event', description:'...', slug:'events/launch' }}
event={{
name: 'Launch Event',
description: 'Product launch',
startDate: '2025-01-01T18:00:00Z',
endDate: '2025-01-01T20:00:00Z',
location: { url: 'https://example.com/live' }, // VirtualLocation
url: 'events/launch'
}}
/>API
Components
SchemaJson(props: SchemaJsonProps)- Emits a single
<script type="application/ld+json">tag containing{"@context":"https://schema.org","@graph":[...]} - Only includes entities for the props you supply
- Emits a single
Configuration
setBaseUrl(url: string)– must be called before using generators; used to build stable@ids andurls
Types
SchemaJsonProps exposes all optional entity props listed above. You can rely on editor IntelliSense without importing individual schema types.
Next.js integration
- App Router: render
SchemaJsoninapp/(segment)/page.tsxorapp/layout.tsx - Pages Router: render in page components or in
_document.tsxinside<Head> - The component uses
dangerouslySetInnerHTMLwith serialized JSON; it’s SSR‑safe
Troubleshooting
- “Base URL is not set. Use
setBaseUrlto configure it.”- Call
setBaseUrl('https://your-domain')once at app startup (layout or_app)
- Call
- Nothing renders
- Ensure you pass at least
logoandwebsite/webpageprops; others are optional
- Ensure you pass at least
Versioning & compatibility
- Peer deps:
reactandreact-dom^18 || ^19 - Target: modern Node/Next.js (ESNext output)
Contributing / Development
pnpm install
pnpm build
pnpm test
# Create a changeset for releases
pnpm changesetReleases are automated via GitHub Actions + Changesets. See .github/workflows/release.yml.
License
MIT
