Structured data
for Astro
Typed Astro components for JSON-LD. Since version 2, every component validates its props – invalid data fails the build instead of going live.
No hand-written JSON in your templates.
The integration holds site-wide defaults such as publisher, brand or business location. Components pick them up, validate their props with Zod and render the finished <script type="application/ld+json">. After rendering, a middleware adds meta tags and, if enabled, a shared @graph block.
- 01Typed — prop types and a Zod schema for every schema type
- 02Strict — invalid or unknown props fail the build
- 03No invented values — missing required data is reported, not filled in
- 04Meta tags —
generateMetaderives Open Graph, Twitter Cards, canonical and hreflang
Three steps to your first schema.
- 1Install
Add the package
The only dependencies are
schema-dtsandzod. Peer dependency: Astro 5, 6 or 7.npm install @casoon/astro-structured-data - 2Configure
Register the integration
siteorsiteUrlis required. Unknown options fail the build.integrations: [structuredData()] - 3Use
Place a component
Regular
.astrocomponents with typed props – in the layout or right on the page.<ArticleSchema title="…" />
What version 2 checks.
Props against Zod
Every component validates its props while rendering. A violation stops the build – or the request in SSR – naming component, page and field.
Unknown props
Typos surface instead of silently dropping data. Only Astro attributes such as slot and data-astro-* are ignored.
Formats
Dates and durations in ISO 8601, currencies in ISO 4217, URLs absolute or root-relative, no empty text fields.
Dependent fields
price only with priceCurrency, ratingValue only with reviewCount, an end date never before the start date.
Per-page rules
In graph mode, every page with schemas needs exactly one <SchemaGraph />. Sitemap hints of all schemas on a page must agree.
Post-build check
Every JSON-LD block in the output is parsed. Invalid JSON fails the build; missing recommended fields show up as warnings.
Config, component, error message.
// astro.config.mjs
import { defineConfig } from 'astro/config';
import structuredData from '@casoon/astro-structured-data';
export default defineConfig({
site: 'https://example.com',
integrations: [
structuredData({
generateMeta: true,
siteName: 'Example',
locale: 'de_DE',
defaultArticlePublisher: {
name: 'Example GmbH',
logo: { url: 'https://example.com/logo.png' },
},
}),
],
});---
import { ArticleSchema, AutoBreadcrumbSchema }
from '@casoon/astro-structured-data/components';
const { post } = Astro.props;
---
<ArticleSchema
title={post.data.title}
description={post.data.description}
datePublished={post.data.date}
authorName={post.data.author}
inLanguage="de"
/>
<AutoBreadcrumbSchema ignoreSegments={['en']} />$ astro build
[astro-structured-data] <EventSchema> on /events/meetup/
received invalid props:
✖ Must be an ISO 4217 currency code like "EUR"
→ at priceCurrency
[structured-data] Organization is missing recommended
field "sameAs" — add it for richer search results.Components for common page types.
Article, FAQ, recipe, video
BlogPosting or NewsArticle with author, series and reading time, FAQPage, Recipe with ingredients and steps, VideoObject with duration and upload date.
Products and listings
Product with offer, brand, GTIN, reviews, shipping and return policy. CollectionPage for category and archive pages.
Company, location, events, jobs
LocalBusiness with address and opening hours, Organization, Event with an in-person, online or hybrid location, JobPosting including remote roles.
Website, page, profile, app
WebSite with an optional sitelinks search box, WebPage for anything without a more specific type, ProfilePage and SoftwareApplication.
Breadcrumbs
BreadcrumbList from an array – or AutoBreadcrumbSchema derives it from the URL path, with custom labels and skipped language segments.
Generic and graph
<Schema> outputs any schema.org object without checking its content. <SchemaGraph /> marks where the shared @graph block goes.
From prop to finished HTML.
- While rendering
Component
Merges props with site-wide defaults, validates them against the Zod schema and emits escaped JSON-LD that content cannot break out of.
- After rendering
Middleware
Sees the complete page: fills in the
@graphblock, inserts meta tags into<head>and runs per-page rules. - After the build
Output check
Parses every JSON-LD block in the generated HTML. Invalid JSON fails the build; missing recommended fields are logged.
Rich result preview in the dev server.
Google-style rendering for Article, FAQ, Product, Breadcrumb, Event, JobPosting, LocalBusiness and SoftwareApplication.
Required and recommended fields per type, for the page you are looking at.
Show the JSON-LD as raw text or copy it to the clipboard.
One click opens validator.schema.org. The panel only appears in astro dev.
What the package does not do.
Structured data describes a page. Whether it becomes a rich result is up to the search engine.
No promise of rich results
The package produces markup following schema.org and Google’s guidelines. How it shows up in search is outside its control.
HTML is buffered
The middleware needs the complete page, so HTML responses are not streamed.
`<Schema>` does not validate
The generic component only requires @type and outputs the object exactly as passed.
Upgrading from 1.x
Version 2 rejects data that 1.x rendered silently. The first build after updating lists everything that needs fixing.
Frequently asked questions.
What is JSON-LD and why do I need it?
JSON-LD is the format Google recommends for structured data. It describes in machine-readable form what a page contains – an article, a product, an FAQ or a business. Search engines use it for rich results, among other things.
What changed in version 2.0?
All data is validated strictly: invalid or unknown props and options fail the build. Missing required values such as an organisation name are no longer invented. Meta tags and the @graph block are produced by a middleware after rendering. Version 2.0.1 fixes an issue with the slot attribute.
How much work is the upgrade from 1.x?
A build reports every invalid value with component, page and field. Typical fixes: add missing names, give baseSalary a unit, set employmentType, operatingSystem and applicationCategory explicitly, and keep exactly one SchemaGraph in the layout in graph mode.
What does graph mode do?
With useGraph: true, the middleware combines all schemas of a page into one @graph block. That avoids repeated @context entries and allows linking entities via @id. SchemaGraph in the layout only determines where the block is placed.
Can I use the Zod schemas in content collections?
Yes. All schemas are exported from @casoon/astro-structured-data/zod and ignore extra frontmatter fields. There is also validateRecommended, which returns the missing recommended fields as a list.
How do I calculate reading time for ArticleSchema?
calculateReadingTime from @casoon/astro-structured-data/utils takes text or HTML and returns wordCount, readingTimeMinutes and timeRequired in ISO 8601 format, for example PT4M. The default is 200 words per minute.
Which Astro versions are supported?
Version 2.0 supports Astro 5, 6 and 7 and requires Node.js 18 or later.
Does it work with astro-post-audit and astro-site-files?
Yes. @casoon/astro-post-audit can check after the build that JSON-LD is present and valid. @casoon/astro-site-files reads the changefreq and priority sitemap hints that every component stores as data attributes on its script tag.
Structured data, checked at build time.
Typed components, strict validation, MIT-licensed.