MallaDocs

Architecture overview

The Workers, the data stores and the six principles the whole platform is built on.

Developer guide

Malla is a Turborepo monorepo of six Cloudflare Workers and a set of shared packages. Everything runs on Cloudflare: Workers, Durable Objects, R2, KV, Queues, Workflows and Hyperdrive in front of Neon Postgres.

text
                      ┌── Cloudflare for SaaS (customer domains + SSL)
visitor ──► sites Worker ──── KV (host → site, publish id)
                │              R2 (snapshots, compiled CSS, assets)
                │              Cache API (rendered pages)
                └─ /api/*, /_auth/* ──► runner Worker ── SiteDatabase DO (tables, visitors)

editor ──► web Worker (Nuxt) ──► api Worker (Hono) ── Hyperdrive ──► Neon Postgres
   │                               ├─ R2 (uploads)   ├─ AI Gateway
   ├─► canvas frames (sandboxed)   └─► sites (publish), runner (test runs)
   └─► realtime Worker: Durable Object per page (Yjs + presence)

The Workers

webThe Nuxt editor and marketing pages. Proxies /api/** to the api over a service binding.
apiHono REST API: auth, sites, pages, CMS, forms, integrations, billing, domains, AI.
realtimeOne Durable Object per page: Yjs sync, presence, checkpoints to Postgres.
sitesPublishes snapshots and serves every published site, form and client query.
runnerServer workflows, crons, durable runs, native tables and visitor auth.
mcpThe MCP server for agents, authenticated with workspace API keys.

Six principles

  1. One document format everywhere. Pages, components and the canvas scratch area share the PageDoc shape.
  2. One renderer. The canvas and the published site run the same @malla/renderer, so what you see is what ships.
  3. One workflow engine. Client and server workflows share a JSON format and @malla/engine, with different adapters.
  4. Built-ins are plugins. REST, GraphQL and the CMS use the same plugin SDK as every other first-party connector.
  5. Never eval user input. Expressions are interpreted from an AST; custom code runs in isolates.
  6. Secrets never reach the browser. Authenticated integration calls are proxied server-side.

From a gesture to the database

GestureA drag, a field edit, an AI tool call.
OpsTyped, validated operations.
YjsApplied to the Y.Doc, undoable.
RoomSynced through the page’s Durable Object.
PostgresCheckpointed as JSON + Yjs state.

See The page document and Realtime.

Where data lives

DataStore
Users, workspaces, sites, pages, CMS, forms, integrations, workflows, billingNeon Postgres (Drizzle, via Hyperdrive)
Live page documents and edit logsDurable Object SQLite per page, checkpointed to Postgres
Native tables, visitors, sessions, form submissionsSiteDatabase Durable Object per site
Uploaded assets, published snapshots, rendered pagesR2
Host routing, published server workflows, entitlements cacheKV
Usage and analyticsAnalytics Engine

Shared packages

PackageRole
@malla/schemaTypes and Zod schemas: PageDoc, ops, styles, data, workflows, CMS, tables, plans
@malla/exprExpression parser and interpreter, built-in functions and autocomplete metadata
@malla/engineWorkflow engine and action registry for the browser and the server
@malla/rendererDocument → HTML/CSS, canvas frame runtime, interactions
@malla/runtimeThe islands runtime published sites load for bindings, forms and workflows
@malla/publishSnapshot publishing and on-demand rendering
@malla/ydocYjs mapping of documents
@malla/plugin-sdk, @malla/pluginsPlugin definitions and the first-party plugins: REST, GraphQL, CMS, Postgres, Supabase, Airtable, Google Sheets, Resend, Anthropic and OpenAI
@malla/bundleSite bundles for templates, sections and copy between sites
@malla/ai-toolsAI and MCP tool schemas that compile to ops
@malla/db, @malla/auth-tokenDrizzle schema and migrations; signed tokens between Workers