npm package: @moonsio/next-schema
Description: 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.
Latest version: 0.16.2

# @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

```bash
pnpm add @moonsio/next-schema
# or
npm i @moonsio/next-schema
```

Peer dependencies you must have in your app:

```json
{
  "peerDependencies": {
    "react": "^18 || ^19",
    "react-dom": "^18 || ^19"
  }
}
```

## Quick start

1) Configure the base URL once at app startup (used to build stable `@id`s):

```tsx
// e.g. app/layout.tsx or pages/_app.tsx
import { setBaseUrl } from '@moonsio/next-schema'

setBaseUrl('https://example.com')
```

2) Render `SchemaJson` on any page. Only pass what you need; we will include the matching entities in `@graph`.

```tsx
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`:

- `address`
- `article`
- `breadcrumb`
- `book`
- `dataset`
- `educationalOrganization`
- `event`
- `faqPage`
- `howTo`
- `logo` (recommended)
- `medicalCondition`
- `medicalOrganization`
- `movie`
- `newsArticle`
- `organization`
- `person`
- `place`
- `product`
- `restaurant`
- `softwareApplication`
- `videoObject`
- `webpage` (recommended)
- `website` (recommended)

## Examples

### Article

```tsx
<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

```tsx
<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)

```tsx
<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

### Configuration

- `setBaseUrl(url: string)` – must be called before using generators; used to build stable `@id`s and `url`s

### 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 `SchemaJson` in `app/(segment)/page.tsx` or `app/layout.tsx`
- Pages Router: render in page components or in `_document.tsx` inside `<Head>`
- The component uses `dangerouslySetInnerHTML` with serialized JSON; it’s SSR‑safe

## Troubleshooting

- “Base URL is not set. Use `setBaseUrl` to configure it.”
  - Call `setBaseUrl('https://your-domain')` once at app startup (layout or `_app`)
- Nothing renders
  - Ensure you pass at least `logo` and `website`/`webpage` props; others are optional

## Versioning & compatibility

- Peer deps: `react` and `react-dom` `^18 || ^19`
- Target: modern Node/Next.js (ESNext output)

## Contributing / Development

```bash
pnpm install
pnpm build
pnpm test

# Create a changeset for releases
pnpm changeset
```

Releases are automated via GitHub Actions + Changesets. See `.github/workflows/release.yml`.

## License

MIT