@malla/renderer is a pure function from documents to HTML and CSS. It runs in the canvas frames, in the sites Worker and in tests, which is why the editor matches production.
renderPage({ doc, components, classes, tokens, site, data, user? })
→ { html, css, runtime: RuntimeManifest }
Snapshot publishing
A publish writes an immutable snapshot (page and component docs, classes, tokens, SEO, manifest) and flips one pointer, so publishing is instant and atomic, and rolling back is another flip. The publish popover and POST /sites/:siteId/rollback flip it back to one of the environment's 50 most recent publishes (see Roll back); CMS items, assets and other live data are not rolled back. Critical pages are prerendered so they are never cold.
On-demand rendering
- Static pages are rendered once per publish and cached forever under keys that include the
publishId. - Server pages run server queries and render per request at the edge, with a short TTL.
- CMS changes bump a revision per collection; only dependent pages render again.
/api/*and/_auth/*go to the runner;/api/_q/*(client queries) and/api/_forms/*stay in sites.
Islands runtime
Published structure is static HTML. Only bound text, attributes, styles and repeated lists change, so @malla/runtime is @vue/reactivity + the shared expression interpreter + a minimal DOM patcher: no virtual DOM, no full hydration, under 25 KB gzipped. It loads only on pages with bindings, forms or client workflows; GSAP is a separate chunk loaded only for interactions.
- The renderer emits an island manifest of what to hydrate.
- Per-request pages embed the visitor in the manifest; cached pages fetch
/_auth/meonce at boot only if something readsuser. - Multi-page navigation uses Speculation Rules prefetch and View Transitions for an app-like feel.
In the canvas
Each artboard is a sandboxed iframe on a separate origin, talking to the editor over a typed postMessage protocol: init, patch with ops, measure, hit-test. Patches touch only the changed node and its CSS rule.