CASOON Open Source
JSON-LD for Astro, typed and validated.
astro-structured-data renders schema.org JSON-LD from Astro components. Props are checked against Zod schemas at build time: invalid data stops the build instead of reaching Google.
npm install @casoon/astro-structured-datapnpm add @casoon/astro-structured-datayarn add @casoon/astro-structured-data{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Structured data for Astro sites",
"description": "How JSON-LD is generated from typed, validated component props.",
"datePublished": "2026-09-10",
"dateModified": "2026-09-12",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://example.com/"
},
"author": {
"@type": "Person",
"name": "Jane Doe"
},
"isAccessibleForFree": true,
"publisher": {
"@type": "Organization",
"name": "Example Blog",
"logo": {
"@type": "ImageObject",
"url": "/logo.png"
}
},
"image": {
"@type": "ImageObject",
"url": "/images/structured-data.jpg"
},
"inLanguage": "en",
"keywords": "astro, json-ld, seo",
"timeRequired": "PT4M"
}- Astro components, one per schema type plus generic and graph
- 18
- Zod schemas exported for content collections and forms
- 16
- tests, including real static, dev and SSR builds
- 232
- client JavaScript added to your pages
- 0 kB
What it does
Validated at build time
Every component parses its props with its Zod schema: ISO 8601 dates, ISO 4217 currencies, absolute or root-relative URLs, cross-field rules. Unknown props are errors, so typos cannot drop data silently.
No invented values
Components never fill in placeholders. A name, a hiring organisation or a salary unit comes from a prop or a configured default, otherwise the build fails.
Meta tags from the same data
With generateMeta, a middleware derives canonical, Open Graph and Twitter tags from the primary schema of the page. Tags your layout already sets are kept.
One @graph per page
With useGraph, all schemas of a page are merged into a single @graph block, wherever the components sit and even when they await data.
Rejected at build time
All examples →[astro-structured-data] <EventSchema> on /events/meetup/ received invalid props:
✖ Invalid input
→ at startDate
✖ Must be an ISO 4217 currency code like "EUR"
→ at priceCurrencyReal output: the error the component throws for examples/invalid-event.astro while this site was built.
examples/invalid-event.astroQuickstart
Register the integration, then place components on your pages. The full walkthrough and every component are in the documentation.
- Install the package and add the integration to
astro.config.mjs. - Set
sitein the Astro config, or passsiteUrlto the integration. - Import components from
@casoon/astro-structured-data/componentsand pass your data as props.
import { defineConfig } from 'astro/config';
import structuredData from '@casoon/astro-structured-data';
export default defineConfig({
site: 'https://example.com',
integrations: [structuredData({ generateMeta: true })],
});