A Docusaurus plugin that automatically generates JSON-LD structured data (schema.org) for your documentation site's SEO. This plugin scans your markdown/MDX files for front matter schema definitions and generates a React Root component that injects the appropriate structured data into each page.
- 🎯 Automatic Schema Generation: Extracts schema definitions from markdown front matter
- 🌐 JSON-LD Output: Generates valid schema.org JSON-LD for SEO
- 🌍 i18n Support: Handles multilingual sites with locale-specific schemas
- ⚙️ Configurable Paths: Support for custom directory structures
- 🔍 Multiple Schema Types: Support for Article, BlogPosting, Organization, Person, Service, and more
- 🛡️ Error Handling: Graceful error handling and recovery
- 🧪 Fully Tested: Comprehensive Jest test suite with 14+ tests
- 📝 Verbose Logging: Optional detailed logging for debugging
- 🔧 TypeScript: Fully typed with TypeScript interfaces
npm install --save @coffeecup_tech/docusaurus-plugin-structured-dataor with yarn:
yarn add @coffeecup_tech/docusaurus-plugin-structured-dataAdd the plugin to your docusaurus.config.js:
module.exports = {
// ... other config
plugins: [
[
'@coffeecup_tech/docusaurus-plugin-structured-data',
{
// Optional: Enable verbose logging
verbose: false,
// Optional: Custom directory paths (relative to siteDir)
srcDir: 'src/pages',
blogDir: 'blog',
docsDir: 'docs',
// Optional: Custom output path for Root.js
outputFile: 'src/theme/Root.js',
// Optional: Fallback image URL for schemas without images
defaultImage: 'https://example.com/default-image.png',
// Base schema for organization/person/website (optional)
baseSchema: {
organization: {
'@id': '${DOCUSAURUS_CONFIG_URL}/#organization',
'@type': 'Organization',
name: 'My Organization',
url: '${DOCUSAURUS_CONFIG_URL}',
logo: '${DOCUSAURUS_CONFIG_URL}/logo.png',
sameAs: '${SAME_AS_DEFAULT}',
},
person: {
'@id': '${DOCUSAURUS_CONFIG_URL}/#person',
'@type': 'Person',
name: 'John Doe',
},
website: {
'@id': '${DOCUSAURUS_CONFIG_URL}/#website',
'@type': 'WebSite',
name: 'My Website',
url: '${DOCUSAURUS_CONFIG_URL}',
},
},
// Optional: i18n specific schemas
i18n: {
fr: {
baseSchema: {
organization: {
'@id': '${DOCUSAURUS_CONFIG_URL}/#organization',
'@type': 'Organization',
name: 'Mon Organisation',
},
},
},
},
// Optional: sameAs default values
sameAsDefault: [
'https://twitter.com/example',
'https://github.com/example',
],
},
],
],
};| Option | Type | Default | Description |
|---|---|---|---|
verbose |
boolean | false | Enable verbose logging during generation |
srcDir |
string | 'src/pages' | Path to pages directory (relative to siteDir) |
blogDir |
string | 'blog' | Path to blog directory (relative to siteDir) |
docsDir |
string | 'docs' | Path to docs directory (relative to siteDir) |
outputFile |
string | 'src/theme/Root.js' | Path where Root.js will be written |
defaultImage |
string | undefined | Fallback image URL for schemas without images |
baseSchema |
object | undefined | Organization/person/website schema structure |
i18n |
object | undefined | Locale-specific schema overrides |
sameAsDefault |
array | [] | Default sameAs URLs for organization |
Add a schema object to the front matter of your markdown/MDX files:
---
title: My Blog Post
slug: my-blog-post
description: This is a great blog post
image: /img/my-image.png
date: 2024-01-15
schema:
type: BlogPosting
headline: My Blog Post
description: This is a great blog post
image: /img/my-image.png
datePublished: 2024-01-15
dateModified: 2024-01-15
---
# My Blog Post
Content here...The plugin automatically enriches the following schema.org types:
- Article - General articles with author/publisher
- BlogPosting - Blog posts with author/publisher
- CollectionPage - Pages that collect other content
- Blog - Blog containers
- AboutPage - About pages
- Service - Services with provider reference
- WebSite - Website metadata
- Organization - Organization information
- Person - Person information
The plugin registers a CLI command with Docusaurus:
npx docusaurus generate-structured-dataThis command:
- Scans all markdown/MDX files in configured directories
- Extracts schema definitions from front matter
- Generates a Root.js component with JSON-LD structured data
- Writes the Root.js file to the specified output path
The plugin automatically adds:
- URL: Current page URL
- mainEntityOfPage: WebPage reference for the current page
- author/publisher: Organization and person references (for Article types)
- provider: Organization reference (for Service types)
- inLanguage: Current locale or 'en-US'
npm run buildCompiles TypeScript from src/ to lib/ directory.
npm run watchAutomatically recompiles on file changes.
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Generate coverage report
npm run test:coverageThe test suite includes:
- Core Functionality Tests: Directory creation, file generation, configuration
- Error Handling Tests: Permission errors, write failures, missing configs
- Schema Generation Tests: JSON-LD validation, type handling, i18n support
A pre-commit hook is configured with Husky to automatically run npm run build before each commit. This ensures the compiled lib/ directory stays in sync with source code.
Simply commit as usual:
git add src/
git commit -m "Your message"
# npm run build runs automatically---
title: Getting Started with Docusaurus
slug: getting-started-docusaurus
description: A comprehensive guide to setting up Docusaurus
image: /img/docusaurus-hero.png
date: 2024-01-10
schema:
type: BlogPosting
headline: Getting Started with Docusaurus
description: A comprehensive guide to setting up Docusaurus
image: /img/docusaurus-hero.png
datePublished: 2024-01-10
dateModified: 2024-01-15
---
# Getting Started with Docusaurus
Your content here...---
title: API Reference
description: Complete API documentation
schema:
type: Article
headline: API Reference
description: Complete API documentation
---
# API Reference
Documentation content...French version (i18n/fr/...):
---
title: Commencer avec Docusaurus
schema:
type: BlogPosting
headline: Commencer avec Docusaurus
description: Un guide complet pour configurer Docusaurus
---
# Commencer avec Docusaurus
Contenu ici...With the i18n configuration, the plugin will use French-specific schema and locale in the generated JSON-LD.
- Plugin Entry (
src/index.ts): Registers the CLI command - Generator (
src/generator.ts): Main logic that:- Scans markdown/MDX files in docs, blog, and src/pages
- Extracts front matter schema definitions
- Generates a React Root component
- Injects JSON-LD
<script type="application/ld+json">tags
The plugin generates a React Root component that:
- Uses the Docusaurus router to get the current page URL
- Looks up schema data for the current path
- Enriches the schema with site-wide metadata
- Injects JSON-LD structured data into the page head
The plugin includes robust error handling:
- Missing Directories: Gracefully skips missing source directories
- File Read Errors: Logs errors and continues processing other files
- Directory Creation: Automatically creates the output directory if missing
- Write Errors: Throws clear error messages if the output file cannot be written
All errors are logged appropriately based on the verbose flag.
- The plugin scans directories only during generation (not at runtime)
- The generated Root.js is optimized for performance
- JSON-LD data is embedded directly in the page (no additional requests)
- i18n locales are handled efficiently with minimal data duplication
- Check that your front matter has a
schemaobject - Verify the file is
.mdor.mdx - Ensure the file is in the scanned directories (src/pages, blog, docs)
- Run with
verbose: trueto see detailed logging
- Verify the
schema.typeis in the supported list - Check that the file path matches the generated route
- Ensure i18n locales are correctly configured
- Ensure the output directory is writable
- Check file permissions on the output location
- Verify disk space is available
Contributions are welcome! Please feel free to submit a Pull Request.
MIT