Skip to content

casoon/astro-structured-data

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@casoon/astro-structured-data

Astro integration for automatic structured data (JSON-LD) generation. Supports Articles, FAQs, Products, Breadcrumbs, Local Businesses, Events, Organizations, and more — with full TypeScript and Zod validation.

Installation

npm install @casoon/astro-structured-data

Setup

Add the integration to your astro.config.mjs:

import { defineConfig } from 'astro/config';
import structuredData from '@casoon/astro-structured-data';

export default defineConfig({
  site: 'https://example.com', // used automatically by the integration
  integrations: [
    structuredData(),
  ],
});

If you don't set site in your Astro config, pass siteUrl explicitly:

structuredData({ siteUrl: 'https://example.com' })

Configuration

Option Type Required Description
siteUrl string No Absolute base URL — falls back to Astro's site config
useGraph boolean No Wrap all schemas in a @graph array
defaultLocalBusiness LocalBusiness No Site-wide local business defaults merged into LocalBusinessSchema
defaultArticlePublisher Organization No Default publisher for ArticleSchema and OrganizationSchema
defaultBrand Brand | string No Default brand for ProductSchema
defaultShippingDetails OfferShippingDetails No Default shipping details for ProductSchema
defaultReturnPolicy MerchantReturnPolicy No Default return policy for ProductSchema

Components

Import components from @casoon/astro-structured-data/components:

---
import { ArticleSchema, FAQSchema } from '@casoon/astro-structured-data/components';
---

ArticleSchema

Docs: schema.org/Article · Google: Article

<ArticleSchema
  title="My Article"
  description="Article description"
  datePublished="2024-01-01"
  authorName="Jane Doe"
  imageUrl="https://example.com/image.jpg"
/>
Prop Type Required Description
title string Yes Article headline
description string Yes Article description
datePublished string | Date Yes Publication date
dateModified string | Date No Last modified date
authorName string | string[] Yes Author name(s)
authorType 'Person' | 'Organization' No Default: 'Person'
imageUrl string | string[] Yes Article image URL(s)
publisherName string No Publisher name (falls back to defaultArticlePublisher)
publisherLogo string No Publisher logo URL (falls back to defaultArticlePublisher)

FAQSchema

Docs: schema.org/FAQPage · Google: FAQ

<FAQSchema
  questions={[
    { question: 'What is this?', answer: 'An Astro integration.' },
    { question: 'How does it work?', answer: 'It injects JSON-LD.' },
  ]}
/>
Prop Type Required Description
questions { question: string; answer: string }[] Yes List of Q&A pairs

ProductSchema

Docs: schema.org/Product · Google: Product

<ProductSchema
  name="Super Gadget"
  description="The best gadget ever"
  imageUrl="https://example.com/gadget.jpg"
  price={29.99}
  priceCurrency="EUR"
  availability="InStock"
  sku="SG-001"
  ratingValue={4.5}
  reviewCount={128}
/>
Prop Type Required Description
name string Yes Product name
description string Yes Product description
imageUrl string | string[] Yes Product image URL(s)
price string | number No Price (simple offer)
priceCurrency string No ISO 4217 currency code, e.g. 'EUR'
availability 'InStock' | 'OutOfStock' | 'PreOrder' | 'OnlineOnly' No Offer availability
offers Offer | Offer[] No Full offer object(s) for advanced use cases
priceRange PriceRange No Price range for variable pricing
brand string | Brand No Brand name or object (falls back to defaultBrand)
sku string No Stock keeping unit
gtin string No GTIN barcode
ratingValue number No Aggregate rating (0–5)
reviewCount number No Number of reviews
reviews ReviewItem[] No Individual review objects
shippingDetails object No Shipping details (falls back to defaultShippingDetails)
returnPolicy object No Return policy (falls back to defaultReturnPolicy)

LocalBusinessSchema

Docs: schema.org/LocalBusiness · Google: Local Business

<LocalBusinessSchema
  name="My Shop"
  telephone="+49 30 1234567"
  address={{
    streetAddress: 'Hauptstraße 42',
    addressLocality: 'Berlin',
    postalCode: '10119',
    addressCountry: 'DE',
  }}
  openingHours={['Mo-Fr 09:00-18:00', 'Sa 10:00-16:00']}
/>

All props fall back to defaultLocalBusiness from the integration config.

Prop Type Required Description
name string No Business name
imageUrl string No Business image URL
telephone string No Phone number
priceRange string No Price range indicator, e.g. '$$'
address { streetAddress, addressLocality, addressRegion?, postalCode, addressCountry } No Postal address
geo { latitude: number; longitude: number } No Geographic coordinates
openingHours string[] No Opening hours, e.g. ['Mo-Fr 09:00-18:00']

BreadcrumbSchema

Docs: schema.org/BreadcrumbList · Google: Breadcrumb

<BreadcrumbSchema
  items={[
    { name: 'Home', url: '/' },
    { name: 'Blog', url: '/blog' },
    { name: 'My Post', url: '/blog/my-post' },
  ]}
/>
Prop Type Required Description
items { name: string; url: string }[] Yes Ordered breadcrumb items

AutoBreadcrumbSchema

Docs: schema.org/BreadcrumbList · Google: Breadcrumb

Generates breadcrumbs automatically from the current URL path. Segments are converted from kebab-case to title case by default.

<AutoBreadcrumbSchema />

<!-- With custom labels -->
<AutoBreadcrumbSchema
  homeLabel="Start"
  labels={{ blog: 'Articles', 'my-post': 'My Post' }}
/>
Prop Type Required Description
homeLabel string No Label for the root segment. Default: 'Home'
labels Record<string, string> No Override labels for specific URL path segments

EventSchema

Docs: schema.org/Event · Google: Event

<EventSchema
  name="Tech Meetup Berlin"
  startDate="2024-06-15T18:00:00"
  locationName="Hub Berlin"
  locationAddress={{
    streetAddress: 'Alexanderplatz 1',
    addressLocality: 'Berlin',
    postalCode: '10178',
    addressCountry: 'DE',
  }}
  attendanceMode="Offline"
  status="Scheduled"
/>
Prop Type Required Description
name string Yes Event name
startDate string | Date Yes Start date/time
endDate string | Date No End date/time
description string No Event description
imageUrl string | string[] No Event image URL(s)
locationName string Yes Venue name
locationAddress { streetAddress, addressLocality, addressRegion?, postalCode, addressCountry } Yes Venue address
attendanceMode 'Offline' | 'Online' | 'Mixed' No Default: 'Offline'
status 'Scheduled' | 'Cancelled' | 'Postponed' | 'Rescheduled' No Default: 'Scheduled'
price number | string No Ticket price
priceCurrency string No ISO 4217 currency code
availability 'InStock' | 'OutOfStock' | 'PreOrder' | 'OnlineOnly' No Ticket availability

OrganizationSchema

Docs: schema.org/Organization · Google: Organization

<OrganizationSchema
  name="ACME Corp"
  logoUrl="https://example.com/logo.png"
  sameAs={['https://twitter.com/acme', 'https://linkedin.com/company/acme']}
/>
Prop Type Required Description
name string No Organization name (falls back to defaultArticlePublisher.name)
url string No Organization URL (falls back to siteUrl)
logoUrl string No Logo URL (falls back to defaultArticlePublisher.logo)
sameAs string[] No Social profile / same-entity URLs
telephone string No Phone number
email string No Email address
address { streetAddress, addressLocality, addressRegion?, postalCode, addressCountry } No Postal address

WebSiteSchema

Docs: schema.org/WebSite · Google: Sitelinks Searchbox

<WebSiteSchema name="My Site" />

<!-- With Sitelinks Searchbox -->
<WebSiteSchema name="My Site" searchQueryInput="q" />
Prop Type Required Description
name string Yes Site name
url string No Site URL (falls back to siteUrl)
searchQueryInput string No URL query param name to enable Sitelinks Searchbox, e.g. 'q'

ProfilePageSchema

Docs: schema.org/ProfilePage · Google: Profile Page

<ProfilePageSchema
  name="Jane Doe"
  description="Software engineer and writer"
  imageUrl="https://example.com/jane.jpg"
  sameAs={['https://github.com/janedoe']}
/>
Prop Type Required Description
name string Yes Person name
description string No Short bio
imageUrl string No Profile image URL
sameAs string[] No Social profile URLs
publishingPrinciples string No URL to editorial / publishing guidelines

CollectionPageSchema

Docs: schema.org/CollectionPage

For product listing / archive pages.

<CollectionPageSchema
  name="All Products"
  description="Browse our full product catalogue"
  products={[
    { name: 'Widget A', url: '/products/widget-a', imageUrl: '...', price: 9.99, priceCurrency: 'EUR' },
    { name: 'Widget B', url: '/products/widget-b' },
  ]}
/>
Prop Type Required Description
name string Yes Page / collection name
description string Yes Collection description
products { name: string; url: string; imageUrl?: string; price?: number | string; priceCurrency?: string }[] Yes List of products

JobPostingSchema

Docs: schema.org/JobPosting · Google: Job Posting

<JobPostingSchema
  title="Senior Developer"
  description="<p>We're looking for a senior developer...</p>"
  datePosted="2024-06-01"
  jobLocation={{
    streetAddress: 'Hauptstraße 1',
    addressLocality: 'Berlin',
    postalCode: '10115',
    addressCountry: 'DE',
  }}
  employmentType="FULL_TIME"
  baseSalary={{ value: 80000, currency: 'EUR', unit: 'YEAR' }}
/>
Prop Type Required Description
title string Yes Job title
description string Yes Job description (HTML accepted by Google)
datePosted string Yes ISO date the posting was published
validThrough string No ISO date the posting expires
employmentType 'FULL_TIME' | 'PART_TIME' | 'CONTRACTOR' | 'TEMPORARY' | 'INTERN' | 'VOLUNTEER' | 'OTHER' No Default: 'FULL_TIME'
hiringOrganizationName string No Hiring company name
hiringOrganizationUrl string No Hiring company URL
hiringOrganizationLogo string No Hiring company logo URL
jobLocation { streetAddress, addressLocality, addressRegion?, postalCode, addressCountry } Yes Job location
baseSalary { value: number | string; currency: string; unit?: 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'YEAR' } No Salary details

SoftwareAppSchema

Docs: schema.org/SoftwareApplication · Google: Software App

<SoftwareAppSchema
  name="My App"
  operatingSystem="Web"
  applicationCategory="BusinessApplication"
  price={0}
  priceCurrency="EUR"
  ratingValue={4.8}
  reviewCount={320}
/>
Prop Type Required Description
name string Yes App name
operatingSystem string No e.g. 'Web', 'Windows, macOS'. Default: 'Web'
applicationCategory string No e.g. 'BusinessApplication', 'Game'. Default: 'DeveloperApplication'
price string | number No Price (use 0 for free apps)
priceCurrency string No ISO 4217 currency code
ratingValue number No Aggregate rating (0–5)
reviewCount number No Number of reviews

SchemaGraph

Renders all schemas registered via useGraph: true as a single @graph block. Place once in your base layout.

---
import { SchemaGraph } from '@casoon/astro-structured-data/components';
---
<SchemaGraph />

No props. Reads from Astro.locals.structuredDataGraph populated by the other components when useGraph is enabled.


Zod schemas

Reusable Zod schemas for all types — useful in Content Collections or form validation:

import {
  articleZodSchema,
  faqZodSchema,
  productZodSchema,
  localBusinessZodSchema,
  eventZodSchema,
} from '@casoon/astro-structured-data/zod';

License

MIT

About

Astro integration for automatic JSON-LD structured data generation

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors