![]() |
VOOZH | about |
dotnet add package Umbraco.Community.SchemeWeaver.uSync --version 1.4.4
NuGet\Install-Package Umbraco.Community.SchemeWeaver.uSync -Version 1.4.4
<PackageReference Include="Umbraco.Community.SchemeWeaver.uSync" Version="1.4.4" />
<PackageVersion Include="Umbraco.Community.SchemeWeaver.uSync" Version="1.4.4" />Directory.Packages.props
<PackageReference Include="Umbraco.Community.SchemeWeaver.uSync" />Project file
paket add Umbraco.Community.SchemeWeaver.uSync --version 1.4.4
#r "nuget: Umbraco.Community.SchemeWeaver.uSync, 1.4.4"
#:package Umbraco.Community.SchemeWeaver.uSync@1.4.4
#addin nuget:?package=Umbraco.Community.SchemeWeaver.uSync&version=1.4.4Install as a Cake Addin
#tool nuget:?package=Umbraco.Community.SchemeWeaver.uSync&version=1.4.4Install as a Cake Tool
Map Umbraco Content Types to Schema.org types and automatically generate JSON-LD structured data for your pages.
👋 Heads-up — I'm building this one in public. SchemeWeaver is usable today, but I'm still dialling in the editor UX and a few of the sharper edges. Expect small behavioural and UI changes between releases while that settles down. Every change (breaking or otherwise) gets called out in the release notes so you can see what's coming before you upgrade.
If something bites you, confuses you, or you just have a suggestion — please open an issue. I genuinely want the feedback, especially the "this UX is weird" kind. The package is better for every issue that gets logged.
SchemeWeaver provides a document type editor 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.
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.
RealEstateListinginLanguage with the BCP 47 culture code. Works across server-rendered templates, the Delivery API, and the backoffice preview/umbraco/delivery/api/v2/schemeweaver/json-ld endpoint returns the per-page JSON-LD blocks, culture-aware, cached in-process with event-driven invalidation on publish/unpublish/move/delete<scheme-weaver content="@Model" /> into any Razor template; the tag helper reads the current culture from Umbraco's IVariationContextAccessor automaticallydotnet 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.
Umbraco 18 made a binary-breaking change to IPublishedContent, so a single assembly cannot run on both majors. SchemeWeaver therefore ships one package per Umbraco major from the same source:
| Umbraco | SchemeWeaver version | Install |
|---|---|---|
| 17 | 1.4.x (stable) |
dotnet add package Umbraco.Community.SchemeWeaver |
| 18 | 1.4.x-umbraco18 (prerelease) |
dotnet add package Umbraco.Community.SchemeWeaver --prerelease |
NuGet picks the right build for your project automatically when you constrain to a major; the -umbraco18 builds are held as prereleases until Umbraco 18.0.0 (and uSync 18.0.0) ship as stable.
To sync schema mappings between environments via uSync:
dotnet add package Umbraco.Community.SchemeWeaver.uSync --prerelease
The uSync addon follows the same per-major scheme (1.4.x for Umbraco 17, 1.4.x-umbraco18 for Umbraco 18). The Umbraco 18 build depends on the uSync 18 release candidate and stays a prerelease until uSync 18.0.0 is stable. See for details.
In your master layout (e.g. _Layout.cshtml):
@addTagHelper *, Umbraco.Community.SchemeWeaver
<head>
...
<scheme-weaver content="@Model" />
</head>
JSON-LD is served from a dedicated endpoint — fetch it in parallel with your content request and inject the strings as <script type="application/ld+json"> tags:
const response = await fetch(
'/umbraco/delivery/api/v2/schemeweaver/json-ld/by-route?route=/my-blog-post',
{ headers: { 'Api-Key': process.env.UMBRACO_DELIVERY_API_KEY! } },
);
const { schemaOrg }: { schemaOrg: string[] } = await response.json();
Responses are cached in-process and invalidated automatically by publish/unpublish/move/delete notifications, so the cache stays fresh without manual busting. The array is ordered: inherited ancestor schemas → BreadcrumbList → main page schema → block-element schemas. See for the full endpoint surface, Next.js example, and the opt-out for BreadcrumbList when your front-end builds its own.
Pre-1.3 consumers who read
schemaOrgfromproperties.schemaOrgon the content response: that was never actually wired up (index handlers feed Examine, not the response body). Use the dedicated endpoint above.
No extra configuration needed. If your content type varies by culture, SchemeWeaver automatically:
VariationContext; the Delivery API handler is called once per culture)inLanguage with the BCP 47 culture code (e.g. "de-DE") unless you've explicitly mapped inLanguage yourself@id and breadcrumb linksMappings stay invariant -- the same mapping applies to all cultures. You don't need per-language mappings; SchemeWeaver resolves the right value at generation time.
The backoffice JSON-LD preview tab automatically follows the workspace variant selector, so switching to German in the editor shows the German JSON-LD output.
Each mapping connects one Umbraco Content Type to one Schema.org type. Within that mapping, individual property mappings define where each schema property gets its value:
| Schema Property | Source | Value | Description |
|---|---|---|---|
headline |
property | title |
Read from the current node |
author |
static | Jane Smith |
Hardcoded string value |
datePublished |
property | publishDate |
Formatted as ISO date |
publisher |
parent | organisationName |
Read from the parent node |
mainEntity |
blockContent | faqItems |
Built from BlockList items |
inLanguage |
(auto) | Auto-populated from the current culture on variant content |
The auto-mapper suggests assignments using three confidence tiers:
title to name, bodyText to articleBody)The generated output:
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "10 Tips for Better SEO",
"author": {
"@type": "Person",
"name": "Jane Smith"
},
"datePublished": "2024-01-15",
"inLanguage": "en-US"
}
acceptedAnswer, reviewRating) require a wrapper type. The auto-mapper pre-configures this for common patterns (FAQ, Product, Recipe). For custom types, see the .Maintainer notes — shipping a new version to NuGet and the Umbraco Marketplace:
NUGET_API_KEY is set in Settings → Secrets and variables → Actions (a single API key with "Push new packages and package versions" scope on Umbraco.Community.SchemeWeaver*).git tag v1.0.0-beta.4 && git push origin v1.0.0-beta.4.Release to NuGet workflow builds, tests, packs and pushes the package to nuget.org, and opens a matching GitHub release.umbraco-marketplace tag (already set in the csproj) and usually updates within 24 hours.To publish an out-of-band build without tagging, use the workflow's "Run workflow" button on the Actions tab and type the version explicitly.
Contributions are very welcome — bug reports, fixes, docs, new property resolvers, extra auto-mapper synonyms, whole new features. Small PRs are fine.
# C#
dotnet build
dotnet test
# Frontend
cd src/Umbraco.Community.SchemeWeaver/App_Plugins/SchemeWeaver
npm install
npm run build
npm test
npm run test:msw # component tests with MSW handlers
npm run test:mocked-backoffice # Playwright drives the real backoffice UI with MSW — needs Umbraco-CMS clone
npm run test:e2e # Playwright against a running Umbraco + .env
npm run test:screenshots # regenerate the docs screenshots (opt-in)
# Test host with 100+ sample content types
dotnet run --project src/Umbraco.Community.SchemeWeaver.TestHost
Note: The TestHost is purely for testing schema mappings and structured data generation. It is not intended as a base site or starter kit.
Read for architecture, DI wiring, and naming conventions.
Please add tests for behavioural changes, and a regression test for bug fixes. CI runs the full suite on every push.
| Layer | Framework | Location |
|---|---|---|
| C# Unit | xUnit + NSubstitute + FluentAssertions | tests/Umbraco.Community.SchemeWeaver.Tests/Unit/ |
| C# Integration | xUnit + WebApplicationFactory<Program> against the SchemeWeaver TestHost, shared via an xUnit collection fixture so every test class reuses a single host (temp SQLite, one file per suite) |
tests/Umbraco.Community.SchemeWeaver.Tests/Integration/ |
| TS Unit / Component | @open-wc/testing + MSW |
App_Plugins/SchemeWeaver/src/**/*.test.ts |
| Mocked Backoffice | Playwright drives the real Umbraco backoffice UI via VITE_EXAMPLE_PATH, with SchemeWeaver's MSW handlers serving all HTTP traffic — no .NET required. Requires a local umbraco/Umbraco-CMS clone plus a small addMockHandlers patch; see |
App_Plugins/SchemeWeaver/tests/mocked-backoffice/ |
| E2E | Playwright + @umbraco/playwright-testhelpers against a running Umbraco |
App_Plugins/SchemeWeaver/tests/e2e/ |
For backoffice UI changes, npm run test:mocked-backoffice verifies manifest wiring, workspace-view conditions, and modal plumbing without a running Umbraco; npm run test:e2e against a real instance is still the only thing that catches issues across the full .NET + backoffice stack.
AI tools (Claude, Codex, Copilot, Cursor, etc.) are welcome to help. The rules are short:
You review it. Read every line before committing. You're accountable for the PR, not the assistant.
MIT-compatible only. Don't submit code copied from incompatible sources.
Add tests, same as any other contribution.
For UI work, install the Umbraco Backoffice Skills and add umbraco/Umbraco-CMS (src/Umbraco.Web.UI.Client) and umbraco/Umbraco.UI (packages/uui) as working directories so the skills can grep the canonical backoffice source — see the skills repo for setup. Also run the umbraco-extension-reviewer agent on UI changes.
Tag the commit. When an assistant materially helped, add a git trailer at the bottom of the commit message so we can see which model was used:
Assisted-by: Claude:claude-opus-4-6
Format is Assisted-by: <agent>:<model> [optional tools], e.g. Assisted-by: Copilot:gpt-5 playwright. Just leave a blank line before it, or use git commit --trailer "Assisted-by=...". Basic tools (git, dotnet, npm, editors) don't need listing. If your tool already adds a Co-authored-by: trailer for the assistant automatically, that's fine too — just don't bother adding both.
Don't add Signed-off-by on a human's behalf. Only the human submitter can sign off their own contribution.
MIT — see . By submitting a pull request you agree to license your contribution under the same terms.
Oliver Picton / Enjoy Digital
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.4.4 | 227 | 6/10/2026 |
| 1.4.4-umbraco18 | 90 | 6/10/2026 |
| 1.4.3 | 394 | 4/22/2026 |
| 1.4.1 | 102 | 4/21/2026 |
| 1.4.0 | 96 | 4/21/2026 |
| 1.3.0 | 108 | 4/18/2026 |
| 1.2.0 | 106 | 4/18/2026 |
| 1.1.0 | 100 | 4/17/2026 |
| 1.0.1 | 105 | 4/17/2026 |
| 1.0.0 | 110 | 4/16/2026 |
| 1.0.0-beta.10 | 62 | 4/16/2026 |
| 1.0.0-beta.9 | 54 | 4/16/2026 |
| 1.0.0-beta.8 | 62 | 4/15/2026 |
| 1.0.0-beta.7 | 61 | 4/15/2026 |
| 1.0.0-beta.6 | 62 | 4/15/2026 |