Compose typed Schema.org entities, validate them with Zod, interconnect them into a unified @graph, and serialize safely for modern web frameworks.
Schema.org JSON-LD gives search engines (Google, Bing) and AI crawlers (Perplexity, ChatGPT Search) machine-readable information about the entities and relationships on a page. Search platforms may use structured data for enhanced features such as Rich Results (Articles, Products, Events, FAQs, Reviews, Breadcrumbs), but valid markup alone does not guarantee eligibility or display.
However, writing JSON-LD by hand or using basic type definitions is error-prone:
- β Silent validation failures: A typo like
publsheror a missing required property can invalidate your structured data without any warning during development or build time. - β Fragmented data silos: Managing entities across independent JSON-LD blocks makes identity reuse, deduplication, and explicit relationships harder to maintain across your authors, articles, organization, and products.
- β Subtle XSS vulnerabilities: Using standard
JSON.stringify()in HTML templates exposes your site to script breakout injections whenever untrusted user or CMS content contains</script>.
unschema-graph provides a typed and validated workflow for the parts it models. It offers 51 Schema.org builders validated at runtime by Zod, an automatic relational engine that resolves #id references into a single, unified @graph, and native components for Astro, Svelte 5, and vanilla TypeScript.
| Feature | Raw <script> / JSON |
schema-dts |
Generic SEO plugins | unschema-graph |
|---|---|---|---|---|
| Strict TypeScript Autocomplete | β | β | Partial | β 51 Dedicated Builders |
| Runtime Validation (Zod) | β | β | β | β Catches dynamic / CMS errors |
Unified @graph Engine |
Manual | β | β | β
Automatic #id deduplication |
| Zero-Trust Anti-XSS Escaping | β | β | Partial | β
Escapes </script> & <!-- |
| Astro Dev Toolbar Inspector | β | β | β | β Live in-browser debug panel |
| Svelte 5 Runes Integration | β | β | β | β
Reactive $derived & $props |
| Static HTML Audit CLI (CI/CD) | β | β | β | β Zero-setup build verification |
| Client Bundle Overhead | 0 kB | 0 kB | 0β15 kB | Astro: 0 kB / Svelte: native runtime |
Create fully validated, interconnected structured data with zero boilerplate:
import { Article, Organization, buildJsonLdGraph, serializeJsonLd } from '@unschema-graph/core';
// 1. Declare typed entities β reference other entities directly as objects!
const publisher = Organization({
'@id': '#organization',
name: 'Acme Media',
url: 'https://example.com'
});
const article = Article({
headline: 'Building Modern Search-Optimized Web Apps',
description: 'How to structure JSON-LD data for search engines and AI agents.',
author: 'Johan Ledoux',
publisher, // π Directly pass the entity object! (Or use '#organization' fragment)
});
// 2. buildJsonLdGraph crawls connected entities, hoists them, and builds a clean @graph
const graph = buildJsonLdGraph(article, { baseUrl: 'https://example.com' });
const jsonLd = serializeJsonLd(graph, { pretty: true });<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://example.com/#organization",
"name": "Acme Media",
"url": "https://example.com"
},
{
"@type": "Article",
"headline": "Building Modern Search-Optimized Web Apps",
"description": "How to structure JSON-LD data for search engines and AI agents.",
"author": { "@type": "Person", "name": "Johan Ledoux" },
"publisher": { "@id": "https://example.com/#organization" }
}
]
}
</script>unschema-graph v0.10.0 freezes the intended public API surface ahead of 1.0.0-rc.1, while preserving the stabilized graph, validation, serialization, Astro and Svelte behavior introduced during the 0.9 cycle.
The curated builder catalog targets the Schema.org 30.1 vocabulary baseline and validates inputs synchronously. Explicitly named profiles such as GoogleArticle and GoogleRecipe add library-maintained Google constraints without implying rich-result eligibility.
Connected knowledge graphs make relationships explicit. Pass entities directly as nested objects (publisher: organization) or reference them via #id fragments. unschema-graph automatically crawls the object graph, hoists shared nodes to the top level, resolves relative #id fragments against your canonical baseUrl, and merges duplicate entities deterministically into a single @graph.
Relationship strings are explicit: fragments, paths, and absolute URIs become @id
references. Plain names expand only when the relationship defines an unambiguous fallback type;
otherwise, pass a typed entity or an explicit @id reference.
Never inject unescaped JSON into your HTML. Our serializer substitutes < and > with Unicode escapes (\u003c, \u003e), guaranteeing that untrusted CMS fields or comments cannot break out of <script> blocks or execute arbitrary JavaScript.
Structured data is processed server-side or during static build. In Astro, the <Schema /> component renders static HTML with no client directive and adds 0 kB of client JavaScript. Core has no client runtime requirement when used during build/SSR. In Svelte, the component integrates with native reactivity and participates in standard hydration and client-side navigation.
Run npx @unschema-graph/core audit dist in your deployment pipeline. The CLI discovers generated HTML files, extracts JSON-LD blocks, checks graph integrity, detects broken local references, duplicate IDs, and structural conflicts before deployment. In this repository, pnpm run audit is the warning-friendly development check, while CI and pnpm run release:check use pnpm run audit:strict so every warning blocks publication.
- Astro: Zero-configuration
<Schema />component, automatic canonical URL resolution fromastro.config.mjs, and an interactive Dev Toolbar app to inspect entities directly in your browser. - Svelte 5: Native reactive component designed with Svelte 5 runes (
$props,$derived), rendering directly into<svelte:head>.
| Package | Environment | Purpose |
|---|---|---|
@unschema-graph/core |
Node >=22.12; browser-safe root; Bun/Deno best-effort | Framework-neutral engine; Node-only audit CLI/API |
@unschema-graph/astro |
Astro 5, 6, 7 | Astro integration, <Schema /> component, Dev Toolbar inspector, Content Collections helpers. |
@unschema-graph/svelte |
Svelte 5 & SvelteKit | Native Svelte 5 <Schema /> component using reactive runes with <svelte:head>. |
Choose the package for your stack:
# For Astro projects
pnpm add @unschema-graph/astro zod
# For Svelte 5 / SvelteKit projects
pnpm add @unschema-graph/svelte zod
# For Node.js, Next.js, Nuxt, or custom pipelines
pnpm add @unschema-graph/core zodExplore the full documentation at unschema-graph.jhdx.dev:
- π Quick Start Guide
- π§ Mental Model & Graph Architecture
- π Complete Catalog of 51 Schema Builders
- π‘οΈ Security & Anti-XSS Hardening
- π Build Audit CLI Guide
- π³ Production Recipes:
unschema-graph is proudly designed and engineered in France with precision, strict typings, and a focus on open-web standards.
Contributions and feedback from the community are warmly welcome!
MIT Β© Johan Ledoux