UI-blind machines
Business logic lives in defineMachine — typed events, guarded
transitions, async effects — with zero knowledge of templates or the DOM.
You can read a checkout flow like a spec, and test it without rendering
anything.
Most frameworks put canonical state in the browser and spend the rest of their API surface keeping it honest with the server. Stator inverts that: a typed state machine on the server is the single source of truth, templates declare exactly what they read from it, and every interaction is an event. The server diffs what changed and sends the DOM a few small patches. No hydration, no client store, no second copy of the truth.
If you’re a TypeScript developer building the kind of software that is fundamentally sessions and server state — shops, dashboards, admin tools, multi-step flows — you’ve been shipping a SPA plus an API to build what is, architecturally, one program. Stator lets you write that one program.
UI-blind machines
Business logic lives in defineMachine — typed events, guarded
transitions, async effects — with zero knowledge of templates or the DOM.
You can read a checkout flow like a spec, and test it without rendering
anything.
Server-canonical reactivity
read(machine, selector) binds a DOM position to state. When an event
changes the answer, that position gets a patch — over the POST response,
or pushed live to every connected session via SSE. Fine-grained updates
without owning a client state stack.
Islands without coloring
When state genuinely belongs in the browser — a theme toggle, a quantity
stepper — the same machine engine runs there as a custom element. No
"use client" pragma: a file is a client island because of what it
structurally is, and the compiler keeps server code out of your bundles.
Honest by construction
Events are typed against each machine’s declared union, on both sides of the wire. Escaping is automatic. The server–client boundary is a line you can point to in every file.
A strong fit: server-authoritative apps — carts and checkouts, internal tools, live dashboards, guarded multi-step flows. Anything where the database is the truth and users share a view of it.
Not the tool: offline-first or local-first apps, canvas-heavy interactive surfaces where nearly everything is client state, static content sites, or systems that must run multi-replica from day one (horizontal scaling is a 1.x path, designed but not shipped).
The longer version, including the tradeoffs you accept, is in Why Stator?
---import Cart from '../machines/cart.ts'
const [cart] = Stator.reads([Cart])---
<p>Items: {read(cart, (c) => c.itemCount)}</p><button on:click={() => cart.send({ type: 'ADD', productId: 'p1' })}> Add to cart</button>The button POSTs a typed event. CartMachine transitions. The <p> gets a
text patch. That’s the whole model — the tutorial
builds a real app on it in eight short chapters.