---
"@type": Article
"@id": "https://helloloam.dev/principles/schema-as-data"
"@source": "https://helloloam.dev/data/article/schema-as-data.json"
"@stamp": "2026-10-22T21:53:55+00:00"
about:
  "@type": DefinedTerm
  "@id": "https://helloloam.dev/data/definedterm/schema-as-data.json"
  name: Schema as data
  identifier: schema-as-data
  inDefinedTermSet:
    "@type": DefinedTermSet
    "@id": "https://helloloam.dev/data/definedtermset/basics.json"
    name: Basics
    identifier: basics
author: {"@id":"https://helloloam.dev/#organization"}
datePublished: "2026-10-03"
description: Every piece of content is a Schema.org record — the vocabulary search engines, browsers and language models already speak.
headline: Schema as data
identifier: schema-as-data
inLanguage: en
publisher: {"@id":"https://helloloam.dev/#organization"}
url: "https://helloloam.dev/principles/schema-as-data"
---

# Schema as data

## A vocabulary the web already speaks

Most content systems invent a model of their own that nobody outside them understands. Loam borrows the one the web already agrees on. An article is an `Article` with a `headline` and an `author`. A business is an `Organization` with an `address`. An event is an `Event` with a `startDate`.

Not as an export, not as an option: the record *is* the content. The page, the machine views and your agent's understanding all turn around it. It is the one choice in loam that is not yours to change — and the one that makes every other part simpler.

## What loam adds: mechanics, not words

Loam adds no vocabulary of its own. It adds four rules for how records live together:

| Mechanic | Rule |
| --- | --- |
| **Identity** | Every entity has an `identifier`; it is also its file name. |
| **References** | Entities point at each other with small references that resolve when the page is read — never a copy. |
| **Pages** | An entity with a `slug` is a page. A list never is: it is curation, shown by a page that reads it. |
| **Required fields** | A handful per type, so a page never goes live without what it needs. |

## Guarded, never policed

The engine guards those mechanics: a reference to nothing, a missing required field, a file that does not parse. Each stops a publish and says why. It never polices meaning — it will not tell you your `Service` should really be a `Product`. What a thing is, is yours to say.

## One record, every reader

Because the fields that render the page are the same fields that feed the structured data, the machine view can only claim what the page shows. The same record is the page a visitor reads, the JSON-LD [a search engine indexes](/principles/seo-friendly), the file at `/data/<type>/<name>.json` and the entry in the index an assistant searches. Nothing is mapped, exported or kept in step by hand.

## In practice

“Make a page for our workshop on 12 March” becomes an `Event` with a `startDate`, a `location` and a slug — your agent knows what an event has without being told, because it has seen millions of them. Before it creates a new kind of thing, it asks the site for that type's shape: which fields exist and which are required. The template reads the same words.

## What it costs

Schema.org has awkward words for some things. The rule: keep the public term where the mechanics do not care, and add a small render-only field where the page needs something the vocabulary lacks — stripped from the machine view so the claim stays true. A moment of thought per type, against a private language every reader would pay for, forever.
