Why I built unschema-graph
Why I wanted a simpler, typed way to build maintainable Schema.org JSON-LD graphs in Astro.
Structured data looks simple when a website only needs a few isolated JSON-LD snippets.
It becomes much harder to maintain once the same person, organization, website or product has to be referenced across multiple pages.
That is the problem I wanted to solve with unschema-graph.
From snippets to a graph
A lot of JSON-LD implementations end up duplicating the same entities everywhere:
{
"@type": "Person",
"name": "Johan Ledoux"
}
The same person might then be declared again in an article, a website, a project and a profile page.
With stable identifiers, these entities can instead become part of the same graph:
https://jhdx.dev/#person
https://jhdx.dev/#website
https://jhdx.dev/#profile
Pages can reference existing entities instead of redefining them.
This makes relationships such as author, publisher or creator much more explicit and predictable.
Why another library?
I wanted an API that felt natural in a TypeScript and Astro project.
The main goals were:
- type safety for Schema.org entities and properties;
- reusable entities instead of duplicated JSON-LD objects;
- stable identifiers for relationships across a website;
- graph composition instead of manually merging snippets;
- an integration that works naturally with Astro’s static rendering.
The goal is not to hide Schema.org.
It is to make implementing it less repetitive and easier to maintain.
Built from a real use case
jhdx.dev itself uses @unschema-graph/astro.
The website connects entities such as the person, website, profile page, open-source project and articles inside the same structured-data model.
That also makes the site a useful real-world test for the library.
unschema-graph is still evolving, but the principle behind it is simple: structured data becomes much easier to reason about when it is treated as a connected graph rather than a collection of unrelated snippets.