Getting started
How sitereal works
site.sitereal, the engine, and the real Astro files that ship.
Three things make up a sitereal project: one document that holds what the builder knows, an engine that turns that document into files, and the files themselves — which are the site.
One file: site.sitereal
Everything the visual interface needs lives in a single JSON document at the project root: site settings, the design system, variables, global styles, installed fonts, components, templates, snippets, content types, media metadata and every page's tree.
{
"format": "sitereal",
"version": 1,
"site": { "name": "My site", "lang": "en" },
"framework": { "enabled": true, "config": { "...": "..." } },
"variables": [],
"styles": [],
"components": [],
"templates": [],
"snippets": [],
"pages": { "index": { "route": "index", "root": [] } }
}It is committed with the project. It replaced a .strata/ folder of sidecar files, which drifted apart, got half-committed, and made "is this folder a project?" a guess. One file moves, copies, versions and diffs as a unit.
The site never reads this file. Nothing emitted may import or fetch it. Delete it and astro build still produces the same site — you lose visual editing, not the site.
The engine
Opening a project starts a local server. It is the only writer of site.sitereal, and it owns emitting: when you save a page it writes that page's .astro file and its CSS; when you change something project-wide — the design system, variables, global styles, templates, snippets, site settings — it re-emits every page, because those things reach into all of them.
Its port and pid go in .sitereal/engine.json, which is gitignored: it describes one process on one machine, not the project.
The same engine serves the builder UI, the MCP tools an agent uses, and the offscreen render the project manager photographs for a card. There is one implementation of every operation.
What a page is
A page is a tree of nodes. One node looks like this:
{
"id": "section-hero",
"tag": "section",
"name": "Hero",
"classes": ["hero"],
"attrs": { "builder-data-element": "section" },
"children": []
}idis stable. It is what the canvas selects and what per-element CSS is keyed to.nameis the layer name — what the tree shows, and what BEM class generation reads.attrsholds every attribute except class, includingbuilder-data-element.textis text content;htmlis raw inner markup, for things that own their markup (an SVG, a highlighted code sample).
The page tree becomes the <main> of the emitted file. A template supplies whatever wraps it.
What gets written
| Path | Written by | Yours to edit |
|---|---|---|
src/pages/<route>.astro | every page save | no — rewritten |
src/components/<Name>.astro | component save | no — rewritten |
src/styles/generated/framework.css | design-system save | no — rewritten |
src/styles/generated/global.css | global styles save | no — rewritten |
src/styles/generated/pages/<route>.css | page save | no — rewritten |
src/styles/generated/templates/<id>.css | template save | no — rewritten |
public/scripts/{nav,motion,overlay}.js | when a page needs one | no — rewritten |
public/robots.txt, public/sitemap.xml | SEO settings, while marked as generated | no |
src/layouts/PlainBase.astro | scaffold, once | yes — it is your file |
| everything else in the repo | you | yes |
The rule is simple: anything under generated/, plus emitted pages and components, is written from the project document. Everything else is yours, and sitereal will not touch it.
Why builder-data-element
Every element carries an attribute naming what it is — section, container, heading, nav-link. The design system styles those attributes:
:where([builder-data-element="section"]) {
padding-block: var(--section-space-m);
padding-inline: var(--gutter);
}Two consequences worth understanding. First, structural styling never depends on a class you might rename — the attribute is the contract, your classes stay yours. Second, :where() contributes zero specificity, so any class or id you write overrides the design system without !important and without caring about source order.
The loop you actually work in
- You edit on the canvas or in a panel.
⌘Ssends the page to the engine.- The engine writes
site.siterealand emits the files. - Astro's dev server, if you have one running, hot-reloads what changed.
There is no build step of ours in that path, and no cache to invalidate.