Events
A contract names every event a session can hold, with a schema for each payload.
Declare the events
import { z } from 'zod'
import * as a2 from 'experimental-a2'
export const orders = a2.contract({
name: 'orders',
events: {
created: z.object({ shopId: z.string(), items: z.array(z.string()) }),
'shop.notified': z.object({}),
'shop.started': z.object({}),
'driver.notified': z.object({ driverId: z.string() }),
expired: z.object({}),
},
})A contract defines what can happen. A session is one instance of it.
name identifies the contract everywhere: in storage, in queue messages, in
logs. It keeps an app with several contracts unambiguous.
events is the full vocabulary. Each key is an event name; each value is a
schema for its payload. These docs use Zod, but any
Standard Schema library works: Valibot, ArkType,
your own.
The contract is a plain, importable, isomorphic value. The server implements it with handlers, reducers derive the current view from it, and the browser types its pushes off it.
Validation
Every append is validated against the contract. A bad payload throws
INVALID_PAYLOAD before anything is written; an unknown type throws
UNKNOWN_EVENT_TYPE. The log stores the validated output, with defaults
applied and transforms run.
Presence
A contract can also declare presence: ephemeral participant state (cursors,
typing, live progress) that is replicated but never stored in the log. See
Presence.