State
Each block has its own state, stored by Reintersect and validated against the block’sstate
schema on every write. Your app keeps no database for blocks.
Date, is a compile error:
Block state is stored as JSON and Standard Schema has no encode step: the state schema must not transform values.
Store dates as ISO strings. On the Effect entry, Effect Schema has an encode step, so
transforming schemas are allowed there.
initialState is checked against the schema. A typo such as { status: "pending" } doesn’t compile.
Stored state is at most 64 KB as JSON.
Actions
An action is a named function that runs when a member clicks a button, submits a form, picks a choice withonChange, searches a Select, or approves an agent’s tool call. Define actions on
their own and attach them to blocks:
src/actions/launch.ts
Options
The name is unique within a block: 1 to 64 characters from
a-z, 0-9, _, . and -.
Handler context
Results
Return nothing, or an object with any of these fields:
After the handler returns, the SDK merges the state, renders the block with it, and sends the new
state and tree back in the same response. Members see the result as soon as Reintersect stores it.
If the handler throws, takes longer than 5 seconds, or returns a state that fails validation,
Reintersect keeps the previous state and tree and shows an error inline to the member who acted.
If the block changed since the member loaded it, the click fails as stale and the block shows its
latest version.
Binding actions in the view
The render context has bound versions of the block’s actions. Pass them to components:ship is destructive, its button needs confirm and can’t be primary. Abort is the
primary button here, and Ship is outlined in the danger colour. In the confirm dialog, the
confirm button repeats the label Ship, and Cancel gets focus first.
The types enforce how each action is used:
What the browser sees
When your view renders, the SDK replaces each bound action with an opaque reference such asa0 and
sends Reintersect a table of what each reference means: the action name and its bound args.
Reintersect keeps that table on the server. The browser only ever sends back the reference, the block
revision and any form input, so a member can’t change the args you bound. Reintersect checks that the
member can act on the block (circle access, audience, install active, block not final) before it calls
your app.
Agents follow the same rule. An agent can only run an action that is rendered in the block right now,
with the args you bound, so it can do exactly what a member could click. See Agents.
Sharing actions across blocks
An action declares only the state it needs. Attaching it to a block checks that slice against the block’s state:Long-running work
Reintersect waits up to 5 seconds for an action. For work that takes longer, return quickly and finish in the background withwaitUntil, then push the result:
waitUntil keeps the Worker alive until the work finishes; on Node it runs the work detached.
Pushing state from your systems
Update blocks from events, routes, cron jobs or your own backend with the client. The block definition is the first argument, so state is typed and the app must include the block:insert, update, replace and updateWhere need blocks:write. Every block has a version that
increases with each change. Pass expectedVersion to make an update conditional; a stale version
fails with ReintersectAppBlockVersionConflictError and nothing changes. Updating a final block
fails with ReintersectAppBlockFinalError. Your app can only change blocks its own install
created.
Each update is validated against the state schema, rendered, and synced to everyone viewing the
block. See Client for authentication and errors, and the
API reference for the HTTP equivalents.