SchemaOrg

A strictly-typed builder for generating SEO Schema.org JSON-LD in Elixir and Phoenix applications.

You should not have to memorise the Schema.org vocabulary. This library ships 1000+ generated struct modules (SchemaOrg.Product, SchemaOrg.Offer, …), one per Schema.org Class. Build a graph with ordinary struct literals — your editor auto-completes the valid fields and the compiler rejects the rest — then serialise it with to_json_ld/1.

%SchemaOrg.Product{
name: "MacBook Pro",
offers: %SchemaOrg.Offer{price: 1999.00, price_currency: "USD"}
}
|> SchemaOrg.to_json_ld()
{
"@context": "https://schema.org",
"@type": "Product",
"name": "MacBook Pro",
"offers": { "@type": "Offer", "price": 1999.0, "priceCurrency": "USD" }
}

Quick Start

mix deps.get # fetch jason + ex_doc
mix compile # compile the library and its generated types
mix test # run the suite

Commands

CommandDescription
mix compileCompile the library and the generated type modules
mix testRun the test suite
mix test --failedRe-run only previously failing tests
mix precommitFormat check + compile (warnings as errors) + full test suite
mix schema_org.build_typesMaintainer only — regenerate lib/schema_org/types/ from the vendored Schema.org graph
mix docsGenerate HTML documentation with ExDoc

Architecture

Two layers, one hand-written and one generated:

priv/schemaorg-current-https.jsonld ──▶ mix schema_org.build_types ──▶ lib/schema_org/types/*.ex
(EEx template)

Documentation

PathContents
docs/specs/Feature specs — one file per capability, updated in place as scope evolves
docs/plans/Implementation plans — one file per spec, task-by-task breakdown with acceptance criteria
docs/decisions/Architecture Decision Records (ADRs) — immutable; record the why behind significant choices
docs/ideas/Early problem framing, refined before a spec is written

Current docs:

Schema.org in Plain Terms

Schema.org is a shared vocabulary that search engines (Google, Bing, Yandex) understand. When you embed it as JSON-LD in a page, you are telling the crawler "this page is about a Product called MacBook Pro that has an Offer of $1999". That structured data is what powers rich results — star ratings, price snippets, breadcrumbs, FAQ accordions.

The vocabulary is a graph of Types (Classes) and Properties:

Writing this JSON by hand is error-prone — there are ~800 types and ~1500 properties, and putting a property on the wrong type produces silently-invalid markup. This library turns that graph into typed Elixir so the compiler and your editor catch mistakes before a crawler ever sees them.


Abbreviations

AbbreviationFull nameWhat it means in this project
JSON-LDJSON for Linking DataThe JSON-based serialisation of Schema.org that search engines read. The output format this library produces
SEOSearch Engine OptimisationThe reason structured data exists — richer, higher-ranking search results
DXDeveloper ExperienceThe guiding goal of this package: typed, autocompletable struct APIs
ClassSchema.org ClassA describable type (Product, Offer). Becomes one generated Elixir module
PropertySchema.org PropertyAn attribute (name, price). Becomes one struct field
domainIncludesThe Schema.org relation declaring which Classes a Property is valid on. Drives field→module mapping
rangeIncludesThe Schema.org relation declaring what value types a Property accepts
EExEmbedded ElixirThe templating language used to render the generated .ex files