How it fits together.

The engine in a dozen moves: a page is a file, a template reads it, an agent changes it through one door. The depth travels with every install — your agent reads it through the MCP.

JSON

A page is a file

An entity with a slug is a page. Its URL, its canonical, its language links and its sitemap line all follow from that one field. The template resolves from its type, so the page renders the moment it exists.

PHP

data()

Reads an entity by type and identifier, in the active language, with its @id and url derived. References to other entities stay stubs until you resolve them — one file, one read.

PHP

rows()

An overview without opening every file: a type gives every entity of it, newest first; an ItemList gives the items in the order you keep. Each row carries the Thing floor — name, description, image, url — plus id, type and date.

PHP

e() and body()

Every field you echo goes through e(). The one sanctioned raw echo is body(), for content that carries HTML — and it floors itself: script tags, event handlers and javascript: links are refused on the way out.

PHP

section(), snippet(), svg(), v()

Four include forms, resolved the same from anywhere and draft-aware in a preview. A missing target renders an HTML comment, never a fatal error. v() is a file's version string, so assets cache for a year and refresh the moment they change.

PHP

seo_head() and ld_page()

The head in three calls: title, description, canonical, Open Graph and hreflang; the PWA layer; and the structured data, built from the entity you render — so the machine view can only claim what the page shows.

Text

The shell ladder

Which template renders a page is a ladder walked on every request: a shell named on the entity, then one named after its type, then the floor every page can land on. No route table to keep — a route line is the exception.

PHP

locale_string()

Interface words live in theme/strings as language maps, one file for every language. A missing word is logged and flagged by the audit — never a silent blank.

PHP

form_gate(), form_store(), form_notify()

A form posts JSON to a route of your own. The gate checks the origin, throttles floods and drops the honeypot; the submission becomes an entity in an inbox that is never served and never in git; the notice goes out by mail.

JSON

The MCP

An agent works through one door. Every verb is checked against its key, every answer is one envelope — ok, a code from a closed set, what to do next — so an agent always knows where it stands.

MCP

The docs travel with the engine

Every install carries its own documentation, for the version it runs. Your agent reads it through the MCP — how loam works, the helpers, the rules — and the site's own guide beside it. No website to reach, nothing out of date.

Shell

The loam command

On the host, one command over the install: judge the content, judge the installation, take a signed update — whole members at a time — and snapshot the site into its own history.

Coming

Bedrock, one layer below draft

The same engine on your own computer, on a copy of your site. Local has no status and no shopfront: build a theme while watching it render, rework a hundred entities without a round trip, then send it back through the MCP — where it is judged like any other change.