> ## Documentation Index
> Fetch the complete documentation index at: https://docs.idyllic.so/llms.txt
> Use this file to discover all available pages before exploring further.

# How It Works

> The client-server architecture behind Idyllic

# 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

```mermaid theme={null}
flowchart TB
    subgraph app["Your Application"]
        subgraph frontend["React Frontend"]
            hook["useSystem&lt;Agent&gt;()"]
            state["state.X"]
            actions["actions.Y()"]
        end

        subgraph runtime["Idyllic Runtime"]
            system["Your System Class"]
            field["@field X"]
            action["@action() Y()"]
        end

        subgraph storage["Durable Storage"]
            sqlite[(SQLite)]
        end

        hook <-->|WebSocket| system
        state <-.->|sync| field
        actions -->|call| action
        system --> sqlite
    end
```

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:

```mermaid theme={null}
flowchart TD
    source["systems/research.ts"] --> transform

    subgraph transform["ts-morph Transform"]
        analyze["Analyze decorators"]
        extract["Extract types"]
    end

    transform --> worker["worker/index.ts<br/>Cloudflare Worker entry"]
    transform --> lib["lib/generated.ts<br/>Client types and hooks"]
    transform --> types["TypeScript Declarations"]

    worker --> deploy[".idyllic/worker.js<br/>Deployed to Cloudflare"]
    lib --> react["React app imports<br/>useSystem&lt;T&gt;()"]
```

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:

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant Server

    Client->>Server: 1. Connect WebSocket
    Server->>Client: 2. Full state snapshot
    Note over Client: 3. Client renders with state
    Client->>Server: 4. User triggers action
    Note over Server: 5. Server executes method
    Server->>Client: 6. State delta (only changed fields)
    Note over Client: 7. Client applies delta, re-renders
    Server-->>Client: ... streaming updates continue ...
```

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:

```typescript theme={null}
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:

```typescript theme={null}
@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.

```mermaid theme={null}
flowchart TB
    subgraph do["Durable Object Instance: research_abc123"]
        subgraph class["Your Class"]
            f1["@field sources = []"]
            f2["@field analysis = stream&lt;string&gt;('')"]
            a1["@action() async analyze(topic)"]
        end

        subgraph conns["Connections"]
            c1["User A"]
            c2["User B"]
            c3["User A (tab 2)"]
        end

        subgraph db["SQLite Storage"]
            fields["state, schedules"]
        end

        class --> db
    end
```

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:

```mermaid theme={null}
sequenceDiagram
    participant A as User A
    participant S as Server
    participant B as User B

    A->>S: analyze("AI safety")
    S->>A: status = 'working'
    S->>B: status = 'working'
    S->>A: analysis.append("chunk")
    S->>B: analysis.append("chunk")
    S->>A: status = 'done'
    S->>B: status = 'done'

    Note over A,B: Both users see same state updates in real-time
```

This enables collaborative applications where multiple users observe the same AI workflow.

## Scheduling and Autonomy

Systems can schedule future execution:

```typescript theme={null}
@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:

```mermaid theme={null}
flowchart TB
    subgraph local["Local Development"]
        subgraph t1["idyllic dev"]
            mini["Miniflare (local CF runtime)"]
            do["Your system as Durable Object"]
            ws["WebSocket on localhost:8787"]
        end

        subgraph t2["npm run dev"]
            react["React dev server"]
            hook["useSystem() connects"]
        end

        t2 <-->|WebSocket| t1
    end
```

State persists across restarts. WebSockets work identically. Your code runs unmodified.

## Deployment

```bash theme={null}
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.

***

<CardGroup cols={2}>
  <Card title="AgenticSystem" icon="cube" href="/concepts/system">
    The system base class API
  </Card>

  <Card title="Deployment" icon="cloud" href="/deployment/cloudflare">
    Production deployment details
  </Card>
</CardGroup>
