Skip to main content

How It Works

Idyllic connects TypeScript classes to React frontends through WebSockets, with automatic state synchronization and type safety. This page explains the architecture.

The Big Picture

When you write an Idyllic application, you work with three pieces:
  1. Your system class - a TypeScript class defining state and behavior
  2. The Idyllic runtime - infrastructure that persists state and handles connections
  3. Your React frontend - components that subscribe to state and call actions
The system class runs on Cloudflare Workers as a Durable Object. When clients connect, they receive current state and subscribe to updates. When they call actions, those execute on the server and state changes propagate to all connected clients.

The Transform Pipeline

When you run idyllic dev or idyllic deploy, your TypeScript class transforms into runtime code: The transform:
  • Extracts @field declarations to generate state schema
  • Extracts @action() methods to generate action interface
  • Generates a Cloudflare Worker hosting your Durable Object
  • Generates client types for full useSystem<T>() type safety
Your single TypeScript class becomes both server implementation and client type contract.

WebSocket Connection Flow

When a React component mounts with useSystem(), a WebSocket connection establishes: Key behaviors:
  • Initial sync: On connect, client receives complete current state
  • Delta updates: After that, only changed fields transmit
  • Streaming: stream<T> fields send incremental chunks as appended
  • Multi-client: All connected clients receive same updates
  • Reconnection: On disconnect, client reconnects and re-syncs

State Synchronization

When you assign to a @field property, the framework detects the change and broadcasts it:
export default class Counter extends AgenticSystem {
  @field count = 0;

  @action()
  async increment() {
    this.count++;  // This assignment triggers sync
  }
}
Behind the scenes:
  1. @field wraps the property in a proxy intercepting assignments
  2. The proxy captures old and new values
  3. New value persists to SQLite in the Durable Object
  4. Delta message broadcasts to all connected WebSocket clients
  5. React hook applies delta and triggers re-render
For streaming, each append() broadcasts the chunk:
@field output = stream<string>('');

@action()
async generate() {
  for await (const chunk of ai.stream('...')) {
    this.output.append(chunk);  // Each append broadcasts
  }
  this.output.complete();
}

The Durable Object Actor

Each system instance runs as a Cloudflare Durable Object—a single-threaded, globally-addressable actor with persistent storage. Properties of Durable Objects:
  • Single-threaded: One method runs at a time—no race conditions
  • Globally unique: Each instance ID maps to exactly one object worldwide
  • Hibernation: Between requests, the object hibernates using no resources
  • Durability: State persists through restarts and deployments
  • Colocated storage: SQLite runs in same location as object

What Idyllic Adds

You could build on raw Durable Objects, but you’d write substantial code:
  • WebSocket connection handling and reconnection
  • State serialization and delta synchronization
  • Client-side state management and re-rendering
  • Type generation for client-server contract
  • Streaming primitives with lifecycle management
Idyllic handles all of this. You write a class, and the framework generates the rest.

Multi-Client Synchronization

Multiple clients connecting to the same instance see identical state: This enables collaborative applications where multiple users observe the same AI workflow.

Scheduling and Autonomy

Systems can schedule future execution:
@action()
async startMonitoring() {
  this.schedule(5 * 60 * 1000, 'check');
}

async check() {
  const issues = await this.scanForIssues();
  if (issues.length > 0) {
    this.issues = issues;
  }
  this.schedule(5 * 60 * 1000, 'check');
}
Between scheduled executions, the Durable Object hibernates. When scheduled time arrives, Cloudflare wakes the object and executes the method.

Local Development

idyllic dev runs a local server mimicking production: State persists across restarts. WebSockets work identically. Your code runs unmodified.

Deployment

npx idyllic deploy
This transforms your classes, bundles worker code, uploads to Cloudflare Workers, configures Durable Object bindings, and returns the production URL. Your system runs on Cloudflare’s global edge network with automatic scaling and low latency worldwide.