Render HTML where your state lives.

Stator is a TypeScript framework where your app’s state lives in machines on the server. An event goes up, a patch comes down. No API layer, no client store, nothing to hydrate.

Start the tutorial$pnpm create stator

One round trip, in three panes. Press something. This is also what the dev toolbar shows you.

BROWSERCart (0)
Pocket Notebook$12.00
Fountain Pen$28.00
Sticky Notes$8.50
WIRE

Quiet. Try Checkout with an empty cart first.

SERVERCartMachine
stateidle
context.items
[]
last transitionnone yet
0 events sent0 bytes of patches

On this page the machine runs in your browser, so the page can sit on a CDN. In your app it runs on the server, and these are the events and patches that would cross the wire.

One program, not two.

No endpoints, no fetch calls, no client copy of your data to go stale. State lives in typed machines on the server, and templates read from them.

Live without writing it.

Add live: true to a route and every open page that reads a changed machine updates, across sessions.

Instant where it matters.

A component with a <script> becomes a client island: the same machine engine in the browser, as a custom element. The compiler checks what ships.

This is the entire test.

Business logic is a machine, so it tests with Node’s own runner. Nothing to install, no DOM, no mock server. This one covers the same cart rules you just pressed.

tests/demo-cart.test.ts
import assert from 'node:assert/strict'
import { it } from 'node:test'
import { createActor } from '@statorjs/stator/machine'
import CartMachine from '../lib/demo-cart.ts'

it('refuses to check out an empty cart', () => {
  const actor = createActor(CartMachine).start()
  actor.send({ type: 'CHECKOUT' })
  assert.deepStrictEqual(actor.getSnapshot().value, ['idle'])
})

No Vite. No Vitest. No build config.

Stator runs your TypeScript directly on Node 24 and ships its own dev server, type checker, test command and production build. The dev server runs your app the way production does.

stator devstator checkstator teststator build
Open the demo

If you know these, you know most of it.

Phoenix LiveView

The closest relative. The server holds the state, diffs it and patches the DOM. Stator brings that model to TypeScript, with state machines as the unit and state in a store you choose.

Pick LiveView when you can be on the BEAM and need to scale across nodes today.

Hotwire and htmx

The same HTML-over-the-wire instinct. Where they swap fragments, Stator sends typed events to typed machines and gets structured patches back.

Pick Hotwire when you are already a Rails shop and the app is shaped like CRUD.

React and RSC

The opposite default. React ships a renderer and marks files as server or client. Stator ships no renderer, and where code runs is decided by where you import it.

Pick React when ecosystem depth or the hiring pool matters most.

NOT A GOAL

Stator is small because it says no. An optimistic update is a second copy of the truth, so there are none; what must be instant lives in a client island. Stator also runs on a single replica today, with scale-out planned.