The layout system
You’ll find it at ACP → Appearance → Layout Editor. A page’s structure is a stored document, not compiled markup: for each template, an ordered list of blocks in each region. The Style Editor decides how things look; the Layout Editor decides what goes where.
Templates
Section titled “Templates”Core ships a fixed set. A layout rearranges pages that already exist; it never creates routes. Plugins can register templates for their own pages (the forum does).
| Template | Renders at | Regions |
|---|---|---|
home |
/ |
main · aside |
article.index |
/articles |
main · aside |
article.detail |
/articles/:slug |
main · aside |
page.detail |
/p/:slug |
main · aside |
profile |
/u/:username |
main · aside |
members |
/members |
main · aside |
chrome.header |
the site header, on every page | header |
chrome.footer |
the site footer, on every page | footer |
main is the page body (the editor labels it “Body”) and aside is the rail beside it.
The login screens and the whole ACP are left out on purpose: you should never be able to
rearrange the screen you’d need to fix a broken arrangement.
Editing
Section titled “Editing”- You see edits right away. The preview is the real page in an iframe, and the editor pushes the document into it before anything is saved.
- The draft autosaves about 700 ms after you stop. There’s no save button.
- Publishing is explicit and covers the whole site. It promotes every pending draft. Open tabs pick up the change within seconds over the style-version SSE stream, without reloading.
- Reset puts the template back to its built-in default. You can’t undo it.
- Drag wherever you like: in the structure tree or straight in the preview, and between regions. The
↑/↓buttons are there for the keyboard. Hover a block to see its outline and type; click it to select it and open its settings. - Block settings are generated from each block’s Zod schema, so nobody hand-writes forms.
- Required blocks (
logoanduserMenuin the navbar) can be moved but not deleted. Both the editor and the API enforce that.
When something goes wrong
Section titled “When something goes wrong”None of these can take a site down:
- A stored document that fails validation: the built-in default renders, and the ACP shows a warning.
- An unknown block type (a plugin got disabled, a block was retired): we skip that block and render the rest. The block stays in the document, so re-enabling the plugin brings it back exactly where it was.
- A block that throws: it renders nothing, and the blocks around it are fine.
Themes are data
Section titled “Themes are data”A .xttheme is a zip of layout documents, tokens, a stylesheet and assets. Never code.
manifest.json id, name, version, vendor, minXentiumVersion, appearancetokens.json the design tokens, by scopestyles/tokens.css the global tokens as :root custom propertiesstyles/custom.css the theme's own stylesheet (optional)layouts/<template>.json one document per templateassets/ images and fontsA theme is one look, light or dark; the manifest says which. Export packages what’s currently published. Import checks everything before it writes anything, so a package with one broken layout doesn’t apply at all. Installing a theme adds it to the site’s theme library, and we ask you whether to switch to it. Since there’s no executable code, reviewing a theme means reading JSON and CSS.
Need a block the catalogue doesn’t have? That’s a plugin, not a theme. See
docs/plugin-blocks.md, and docs/style-system.md
for how themes and tokens fit together.