
Structured data is one of those things every developer knows they should implement, but few actually...
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?
Here's what typical JSON-LD looks like:
{
"@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:
@context?datePublished in the right format?Article as Aticle?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
Instead of hand-writing JSON:
// ❌ 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:
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.
Good news: Schema Sentry works identically with both Next.js routing patterns.
// 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/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.
Schema Sentry includes builders for the most common types:
Here's where it gets powerful. Schema Sentry includes a CLI for automated validation:
// 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:
# .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:
Google uses JSON-LD to create rich snippets in search results:
This is the big one that most developers are missing. AI systems like:
# 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:
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.
Check out the complete working examples:
Adding structured data doesn't have to be painful:
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 if you found this helpful!
gemmaI ported the whole Gemma-4 family — E2B, E4B, 12B, 31B, and the 26B-A4B MoE — to run on...
communityHey DEV, I'm Tobore. Let's actually connect. I've been on here for a while now, mostly writing and...
ai(yep, kinda clickbait, just for the funsies 😊) At the beginning of the year, I relaunched my...
aiMy laptop was sitting idle with the fan at full tilt. Nothing was running that I knew of. The culprit...
githubactionsI Built a Thing! TL;DR — Google Gemini-based Pull Request reviews and Issue Triaging for...
aiI've been hearing the word "harness" thrown around a lot lately. I assumed it just meant "the IDE" or...
Workflows from the Neura Market marketplace related to this DeepSeek resource