Structured data is one of those things every developer knows they *should* implement, but few actually do. Why? Because writing JSON-LD by hand is error-prone, tedious, and easy to get wrong.
What if you could generate type-safe structured data with autocomplete, validation, and zero runtime overhead?
## The Problem with JSON-LD
Here's what typical JSON-LD looks like:
```json
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "My Blog Post",
"author": {
"@type": "Person",
"name": "Jane Doe"
},
"datePublished": "2026-02-10"
}
```
Looks simple, right? But try maintaining this across dozens of pages:
- Did you forget the `@context`?
- Is `datePublished` in the right format?
- Did you typo `Article` as `Aticle`?
- Is this even valid according to schema.org?
**These mistakes cost you search rankings and AI visibility.**
## Enter Schema Sentry
[Schema Sentry](https://github.com/arindamdawn/schema-sentry) is a type-safe library for generating JSON-LD structured data. It gives you:
✅ **Full TypeScript autocomplete** - No more guessing field names
✅ **Compile-time validation** - Catch errors before they reach production
✅ **Zero runtime overhead** - Everything happens at build time
✅ **Works with both Pages Router and App Router** - Your choice of Next.js patterns
✅ **CI/CD validation** - Automated checks in your pipeline
## Quick Example
Instead of hand-writing JSON:
```tsx
// ❌ Error-prone manual JSON
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "Article",
"headline": "My Post",
// Did I get all required fields? Who knows!
})
}}
/>
```
Use type-safe builders:
```tsx
import { Schema, Article } from "@schemasentry/next";
// ✅ Type-safe with autocomplete
const article = Article({
headline: "My Post",
authorName: "Jane Doe",
datePublished: "2026-02-10",
url: "https://example.com/blog/post",
});
export default function Page() {
return <Schema data={article} />;
}
```
**Same output, zero guesswork.**
## Pages Router vs App Router
Good news: Schema Sentry works identically with both Next.js routing patterns.
### App Router (Next.js 13+)
```tsx
// app/blog/[slug]/page.tsx
import { Schema, Article, BreadcrumbList } from "@schemasentry/next";
export default function BlogPost({ params }: { params: { slug: string } }) {
const article = Article({
headline: "Getting Started",
authorName: "Jane Doe",
datePublished: "2026-02-10",
url: `https://example.com/blog/${params.slug}`,
});
const breadcrumbs = BreadcrumbList({
items: [
{ name: "Home", url: "https://example.com" },
{ name: "Blog", url: "https://example.com/blog" },
],
});
return (
<>
<Schema data={[article, breadcrumbs]} />
<article>{/* content */}</article>
</>
);
}
```
### Pages Router (Classic Next.js)
```tsx
// pages/blog/[slug].tsx
import Head from "next/head";
import { Schema, Article, BreadcrumbList } from "@schemasentry/next";
export default function BlogPost() {
const article = Article({
headline: "Getting Started",
authorName: "Jane Doe",
datePublished: "2026-02-10",
url: "https://example.com/blog/post",
});
const breadcrumbs = BreadcrumbList({
items: [
{ name: "Home", url: "https://example.com" },
{ name: "Blog", url: "https://example.com/blog" },
],
});
return (
<>
<Head>
<title>Getting Started - My Blog</title>
</Head>
<Schema data={[article, breadcrumbs]} />
<article>{/* content */}</article>
</>
);
}
```
**The only difference?** App Router doesn't need `next/head` because it supports native metadata.
## Supported Schema Types
Schema Sentry includes builders for the most common types:
- **Organization** - Company/publisher info
- **WebSite** - Site metadata
- **Article** / **BlogPosting** - Blog posts and articles
- **Product** - E-commerce products with offers
- **FAQPage** - FAQ sections with expandable questions
- **HowTo** - Step-by-step guides
- **BreadcrumbList** - Navigation breadcrumbs
- **Person** - Author/contributor info
## CI/CD Validation
Here's where it gets powerful. Schema Sentry includes a CLI for automated validation:
```json
// schema-sentry.manifest.json
{
"routes": {
"/": ["Organization", "WebSite"],
"/blog": ["WebSite"],
"/blog/getting-started": ["Article"],
"/products/widget": ["Organization", "Product"],
"/faq": ["FAQPage", "Organization"]
}
}
```
Add to your GitHub Actions:
```yaml
# .github/workflows/schema-check.yml
name: Schema Validation
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- run: pnpm install
- run: pnpm build
- run: pnpm schemasentry validate
```
Now your CI will fail if:
- A page is missing expected schema
- Schema types don't match the manifest
- Invalid JSON-LD is generated
**Never ship broken structured data again.**
## Why Structured Data Matters
### For Traditional SEO
Google uses JSON-LD to create rich snippets in search results:
- Article headlines and publication dates
- Product prices and ratings
- FAQ dropdowns
- Breadcrumb navigation
These rich results get **higher click-through rates** than plain blue links.
### For AI Discovery
This is the big one that most developers are missing. AI systems like:
- ChatGPT
- Claude
- Perplexity
- Google Bard
...all use structured data to understand and cite content. Without proper schema, your content is invisible to the AI discovery layer.
## Getting Started
```bash
# Install packages
npm install @schemasentry/next
npm install -D @schemasentry/cli
# Or with pnpm
pnpm add @schemasentry/next
pnpm add -D @schemasentry/cli
```
Create your first schema:
```tsx
import { Schema, Organization } from "@schemasentry/next";
const org = Organization({
name: "My Company",
url: "https://example.com",
logo: "https://example.com/logo.png",
description: "We build amazing things",
});
export default function Home() {
return (
<>
<Schema data={org} />
<h1>Welcome</h1>
</>
);
}
```
That's it! The `<Schema />` component injects the JSON-LD into your page's `<head>` automatically.
## Live Examples
Check out the complete working examples:
- **[App Router Example](https://github.com/arindamdawn/schema-sentry/tree/main/examples/next-app)** - Modern Next.js 13+ patterns
- **[Pages Router Example](https://github.com/arindamdawn/schema-sentry/tree/main/examples/next-pages)** - Classic Next.js patterns
Both demonstrate the same UI with all 11+ schema types.
## Summary
Adding structured data doesn't have to be painful:
1. **Type safety** catches errors at compile time
2. **Autocomplete** guides you to the right fields
3. **CI validation** prevents broken schema from shipping
4. **Zero runtime cost** - everything is static
5. **Works with any Next.js routing pattern**
Your future self (and your search rankings) will thank you.
---
**Have you implemented structured data on your Next.js site? What challenges did you face?**
*Schema Sentry is open source under MIT license. Star us on [GitHub](https://github.com/arindamdawn/schema-sentry) if you found this helpful!*