Umbraco.Community.SchemeWeaver
1.0.0-beta
See the version list below for details.
dotnet add package Umbraco.Community.SchemeWeaver --version 1.0.0-beta
NuGet\Install-Package Umbraco.Community.SchemeWeaver -Version 1.0.0-beta
<PackageReference Include="Umbraco.Community.SchemeWeaver" Version="1.0.0-beta" />
<PackageVersion Include="Umbraco.Community.SchemeWeaver" Version="1.0.0-beta" />
<PackageReference Include="Umbraco.Community.SchemeWeaver" />
paket add Umbraco.Community.SchemeWeaver --version 1.0.0-beta
#r "nuget: Umbraco.Community.SchemeWeaver, 1.0.0-beta"
#:package Umbraco.Community.SchemeWeaver@1.0.0-beta
#addin nuget:?package=Umbraco.Community.SchemeWeaver&version=1.0.0-beta&prerelease
#tool nuget:?package=Umbraco.Community.SchemeWeaver&version=1.0.0-beta&prerelease
Umbraco.Community.SchemeWeaver
Map Umbraco Content Types to Schema.org types and automatically generate JSON-LD structured data for your pages. SchemeWeaver provides a backoffice UI for configuring mappings, an auto-mapper that suggests property assignments, and runtime JSON-LD generation that works with both server-rendered templates and the headless Delivery API.
Why structured data?
Search engines use JSON-LD to understand page content. A blog post tagged as BlogPosting with a headline, author, and datePublished can appear as a rich result in Google, Bing, and other search engines. Manually maintaining JSON-LD scripts is tedious and error-prone -- SchemeWeaver automates it from your existing content.
Features
- 500+ Schema.org types -- discovers every type in the Schema.NET library at startup (Article, Product, FAQPage, Event, Person, Organisation, and hundreds more)
- Auto-mapping with confidence scores -- suggests property mappings using exact matching, synonym dictionaries, and substring matching, each with a transparency score so you can verify suggestions
- Seven source types -- pull values from the current node, a static value, the parent node, an ancestor of a specific type, a sibling node, block content, or nested complex types
- Transforms -- strip HTML, convert to absolute URL, or format dates before output
- Backoffice dashboard -- bulk view and manage all content type mappings from the Settings section
- Workspace view -- edit the Schema.org mapping directly from the Content Type editor
- Entity actions -- right-click a Content Type to map it or generate a new one from a schema
- Content Type generation -- scaffold a new Umbraco document type from any Schema.org type, with properties pre-grouped into Content, SEO, and Metadata tabs
- Delivery API integration -- JSON-LD is automatically indexed and available via the
schemaOrgfield in API responses - Tag helper -- drop
<scheme-weaver content="@Model" />into any Razor template to render the JSON-LD script tag - Inherited schemas -- mark a mapping as inherited and it outputs on all descendant pages (e.g. Organisation schema on the homepage cascading site-wide)
- Automatic block traversal -- BlockList/BlockGrid elements with their own schema mappings are automatically rendered as separate JSON-LD blocks, zero configuration needed
- BreadcrumbList auto-generation -- a BreadcrumbList JSON-LD block is automatically generated from the content's ancestor hierarchy
- @id for AI discoverability -- each schema output includes an
@idset to the content's absolute URL - Localisation -- all UI strings use Umbraco's localisation system
Requirements
- Umbraco 17+
- .NET 10
Installation
dotnet add package Umbraco.Community.SchemeWeaver
No additional configuration needed. The package registers all services, creates its database tables on first run, and adds the backoffice UI automatically.
How it works
The mapping model
Each mapping connects one Umbraco Content Type to one Schema.org type:
Content Type: blogPost
maps to
Schema.org Type: BlogPosting
Within that mapping, individual property mappings define where each schema property gets its value:
| Schema Property | Source Type | Value | Description |
|---|---|---|---|
headline |
property | title |
Read from the current node's title property |
author |
static | Jane Smith |
Hardcoded string value |
datePublished |
property | publishDate |
Read from publishDate, formatted as ISO date |
publisher |
parent | organisationName |
Read from the parent node |
articleSection |
ancestor | categoryName on blogRoot |
Walk up the tree to find a blogRoot node, read its categoryName |
about |
sibling | topicDescription on topicPage |
Find a sibling of type topicPage, read its topicDescription |
Source types explained
| Source | Behaviour |
|---|---|
| property | Reads a property from the current content node |
| static | Uses a hardcoded string value (useful for @type, organisation names, etc.) |
| parent | Reads a property from the immediate parent node |
| ancestor | Walks up the content tree to find the first ancestor matching a specific content type alias, then reads the property |
| sibling | Looks at the parent's children to find the first sibling matching a specific content type alias, then reads the property |
| blockContent | Extracts values from BlockList/BlockGrid items, creating nested Schema.org objects |
| complexType | Creates a nested Schema.org type with its own sub-property mappings |
Auto-mapping algorithm
When you map a content type to a schema type, the auto-mapper suggests property assignments using three tiers:
- Exact match (100% confidence) -- property alias matches schema property name exactly (case-insensitive)
- Synonym match (80% confidence) -- uses a built-in dictionary of common aliases:
namematchestitle,heading,pageTitle,nodeNamedescriptionmatchesmetaDescription,excerpt,summaryarticleBodymatchescontent,bodyText,richText,mainContentimagematchesheroImage,mainImage,thumbnail,featuredImagedatePublishedmatchespublishDate,createDate,articleDate- ...and 20+ more synonym groups
- Partial match (50% confidence) -- schema property name appears as a substring in the Umbraco property alias (e.g.,
namematchesauthorName)
Unmatched schema properties appear with 0% confidence so you can configure them manually.
JSON-LD generation
At runtime (on publish or page request), the JsonLdGenerator service:
- Looks up the mapping for the content type
- Creates a Schema.NET object (e.g.,
BlogPosting) - For each property mapping, resolves the value using the configured source type
- Applies any transforms (strip HTML, format date, make URL absolute)
- Sets the value on the Schema.NET object using reflection and implicit type operators
- Serialises to JSON-LD
The generated output looks like:
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "10 Tips for Better SEO",
"author": {
"@type": "Person",
"name": "Jane Smith"
},
"datePublished": "2024-01-15",
"articleBody": "Full article content here..."
}
Usage
Option 1: Tag helper (server-rendered sites)
In any Razor template or view:
@addTagHelper *, Umbraco.Community.SchemeWeaver
<scheme-weaver content="@Model" />
This renders <script type="application/ld+json"> tags with the generated JSON-LD (main schema, BreadcrumbList, inherited ancestor schemas, and auto-discovered block element schemas). If the content type has no mapping or the mapping is disabled, nothing is rendered.
Option 2: Delivery API (headless sites)
JSON-LD is automatically indexed when content is published. Fetch it from the Delivery API response:
const response = await fetch('/umbraco/delivery/api/v2/content/item/my-blog-post');
const data = await response.json();
// JSON-LD is in the schemaOrg field
const jsonLd = data.properties.schemaOrg;
if (jsonLd) {
const script = document.createElement('script');
script.type = 'application/ld+json';
script.textContent = jsonLd;
document.head.appendChild(script);
}
Option 3: Direct service injection
@inject IJsonLdGenerator JsonLdGenerator
@{
var jsonLd = JsonLdGenerator.GenerateJsonLdString(Model);
if (!string.IsNullOrEmpty(jsonLd))
{
<script type="application/ld+json">@Html.Raw(jsonLd)</script>
}
}
Backoffice UI
Dashboard
Navigate to Settings > Schema.org Mappings to see all content types with their mapping status:
- Mapped content types show the Schema.org type, property count, and action buttons (Edit, Preview, Delete)
- Unmapped content types have a "Map" button to start the mapping flow
- Search and filter content types by name or alias
Mapping flow
- Click Map on an unmapped content type
- Schema Picker modal opens -- browse or search 500+ Schema.org types, grouped by parent type
- Select a type and click Select
- Property Mapping modal opens -- auto-mapped suggestions appear with confidence badges:
- High (green, 80%+) -- very likely correct
- Medium (amber, 50%+) -- probable match, worth checking
- Low (red, <50%) -- needs manual review
- Adjust source types and values as needed
- Click Generate Preview to see the JSON-LD output
- Click Save to persist the mapping
Content Type generation
From the dashboard or via entity action, you can generate a new Umbraco Content Type from any Schema.org type:
- Select a Schema.org type
- Choose which properties to include
- SchemeWeaver creates the Content Type with:
- Properties mapped to appropriate editors (Textstring, Rich Text, Date Picker, etc.)
- Properties grouped into Content, SEO, and Metadata tabs
- The Schema.org mapping pre-configured
Database
SchemeWeaver creates two tables on first run via Umbraco's migration system:
SchemeWeaverSchemaMapping
| Column | Type | Description |
|---|---|---|
| Id | int (PK) | Auto-increment |
| ContentTypeAlias | string (unique) | Umbraco content type alias |
| ContentTypeKey | Guid | Umbraco content type key |
| SchemaTypeName | string | Schema.org type name (e.g., "BlogPosting") |
| IsEnabled | bool | Whether JSON-LD generation is active |
| IsInherited | bool | Whether this schema is also output on all descendant pages |
| CreatedDate | DateTime | When the mapping was created |
| UpdatedDate | DateTime | Last modification time |
SchemeWeaverPropertyMapping
| Column | Type | Description |
|---|---|---|
| Id | int (PK) | Auto-increment |
| SchemaMappingId | int (FK) | References SchemaMapping |
| SchemaPropertyName | string | Schema.org property (e.g., "headline") |
| SourceType | string | "property", "static", "parent", "ancestor", "sibling", "blockContent", or "complexType" |
| ContentTypePropertyAlias | string? | Which Umbraco property to read |
| SourceContentTypeAlias | string? | For ancestor/sibling: which content type to look for |
| TransformType | string? | "stripHtml", "toAbsoluteUrl", or "formatDate" |
| IsAutoMapped | bool | Whether this was created by the auto-mapper |
| StaticValue | string? | Hardcoded value (when source type is "static") |
| NestedSchemaTypeName | string? | For complex nested schema types |
| ResolverConfig | text? | JSON configuration for nested property mappings and block content extraction |
API reference
All endpoints are under /umbraco/management/api/v1/schemeweaver and require backoffice authentication.
Schema types
| Method | Endpoint | Description |
|---|---|---|
| GET | /schema-types?search={query} |
List or search Schema.org types |
| GET | /schema-types/{name}/properties |
Get properties for a schema type |
Content types
| Method | Endpoint | Description |
|---|---|---|
| GET | /content-types |
List all Umbraco content types |
| GET | /content-types/{alias}/properties |
Get properties for a content type |
Mappings
| Method | Endpoint | Description |
|---|---|---|
| GET | /mappings |
Get all mappings |
| GET | /mappings/{alias} |
Get mapping for a content type |
| POST | /mappings |
Create or update a mapping |
| DELETE | /mappings/{alias} |
Delete a mapping |
| POST | /mappings/{alias}/auto-map?schemaTypeName={name} |
Get auto-mapping suggestions |
| POST | /mappings/{alias}/preview?contentKey={key} |
Preview JSON-LD for a content item |
Content type generation
| Method | Endpoint | Description |
|---|---|---|
| POST | /generate-content-type |
Create a content type from a schema |
Architecture
Umbraco Backoffice
|
v
SchemeWeaver Dashboard / Modals / Workspace View (Lit Web Components)
|
v
SchemeWeaverServerDataSource (fetch wrapper)
|
v
SchemeWeaverApiController (Management API)
|
v
SchemeWeaverService (orchestrator)
|
+---> SchemaTypeRegistry (singleton, scans Schema.NET assembly)
+---> SchemaMappingRepository (NPoco, reads/writes database)
+---> SchemaAutoMapper (suggests property mappings)
+---> JsonLdGenerator (produces JSON-LD from IPublishedContent)
+---> ContentTypeGenerator (creates Umbraco content types)
Runtime Output:
JsonLdGenerator -----> TagHelper (<scheme-weaver> in Razor)
JsonLdGenerator -----> SchemaJsonLdContentIndexHandler (Delivery API)
Development
Prerequisites
- .NET 10 SDK
- Node.js 22+
Build
# Full solution (backend + TestHost)
dotnet build
# Frontend (from App_Plugins/SchemeWeaver/)
cd src/Umbraco.Community.SchemeWeaver/App_Plugins/SchemeWeaver
npm install
npm run build # builds to ../../wwwroot/dist/
Test
# C# unit tests (215 tests)
dotnet test
# Frontend unit + component tests
cd src/Umbraco.Community.SchemeWeaver/App_Plugins/SchemeWeaver
npm test
TestHost
A runnable Umbraco 17 instance is included for local development and testing:
dotnet run --project src/SchemeWeaver.TestHost
Login at http://localhost:5000/umbraco with admin@test.com / SecurePass1234.
Pack
dotnet pack src/Umbraco.Community.SchemeWeaver/Umbraco.Community.SchemeWeaver.csproj \
--configuration Release --output ./artifacts
Licence
MIT -- see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Schema.NET (>= 13.0.0)
- Umbraco.Cms (>= 17.2.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Umbraco.Community.SchemeWeaver:
| Package | Downloads |
|---|---|
|
Umbraco.Community.SchemeWeaver.uSync
uSync addon for SchemeWeaver — syncs Schema.org mappings (including resolver config and dynamic root config) between Umbraco environments alongside the doc types they belong to. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 1.4.3 | 271 | 4/22/2026 | |
| 1.4.1 | 112 | 4/21/2026 | |
| 1.4.0 | 105 | 4/21/2026 | |
| 1.3.0 | 114 | 4/18/2026 | |
| 1.2.0 | 104 | 4/18/2026 | |
| 1.1.0 | 105 | 4/17/2026 | |
| 1.0.1 | 114 | 4/17/2026 | |
| 1.0.0 | 106 | 4/16/2026 | |
| 1.0.0-beta.10 | 55 | 4/16/2026 | |
| 1.0.0-beta.9 | 56 | 4/16/2026 | |
| 1.0.0-beta.8 | 63 | 4/15/2026 | |
| 1.0.0-beta.7 | 57 | 4/15/2026 | |
| 1.0.0-beta.6 | 60 | 4/15/2026 | |
| 1.0.0-beta.5 | 62 | 4/15/2026 | |
| 1.0.0-beta.2 | 82 | 3/23/2026 | |
| 1.0.0-beta | 134 | 3/23/2026 |