or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication.mdclient-runtime.mddatabase.mde2e-testing.mdindex.mdrealtime.mdrouting.mdsynced-state.mdturnstile.mdvite-plugin.mdworker-runtime.md
tile.json

realtime.mddocs/

Realtime Features

WebSocket-based realtime functionality with Durable Objects for server-side coordination and selective client rendering.

Capabilities

Realtime Route (Server)

Creates a route handler for realtime WebSocket connections.

/**
 * Creates a realtime route handler for WebSocket connections
 * @param getDurableObjectNamespace - Function to get the Durable Object namespace from env
 * @returns Route definition for the realtime endpoint
 */
function realtimeRoute(
  getDurableObjectNamespace: (env: any) => DurableObjectNamespace<RealtimeDurableObject>
): Route<any>;

Usage Example:

import { defineApp, route } from 'rwsdk/router';
import { realtimeRoute } from 'rwsdk/realtime/worker';

export default defineApp([
  // Realtime route for WebSocket connections
  realtimeRoute((env) => env.REALTIME_DO),

  // Regular routes
  route('/', HomePage),
]);

Render Realtime Clients (Server)

Triggers a re-render for connected realtime clients with selective targeting.

/**
 * Triggers render for connected realtime clients
 * @param options - Rendering options
 */
function renderRealtimeClients(options: {
  /** Durable Object namespace for realtime coordination */
  durableObjectNamespace: DurableObjectNamespace<RealtimeDurableObject>;
  /** Realtime key for grouping clients (default: DEFAULT_REALTIME_KEY) */
  key?: string;
  /** Specific client IDs to include (optional) */
  include?: string[];
  /** Specific client IDs to exclude (optional) */
  exclude?: string[];
}): Promise<void>;

Usage Example:

import { renderRealtimeClients } from 'rwsdk/realtime/worker';

// In a server function that updates data
async function updatePost(postId: string, env: any) {
  // Update the post in database
  await updatePostInDb(postId);

  // Trigger re-render for all connected clients
  await renderRealtimeClients({
    durableObjectNamespace: env.REALTIME_DO,
  });
}

// Selective rendering - only specific clients
async function sendNotification(userId: string, env: any) {
  await renderRealtimeClients({
    durableObjectNamespace: env.REALTIME_DO,
    include: [userId], // Only render for this user
  });
}

// Exclude specific clients (e.g., the one who made the change)
async function broadcastUpdate(excludeClientId: string, env: any) {
  await renderRealtimeClients({
    durableObjectNamespace: env.REALTIME_DO,
    exclude: [excludeClientId],
  });
}

Realtime Client Initialization

Initializes the realtime client with WebSocket connection.

/**
 * Initializes realtime client with WebSocket connection
 * @param options - Client initialization options
 */
function initRealtimeClient(options?: {
  /** Realtime key for grouping (default: "default") */
  key?: string;
  /** Custom response handler for navigation */
  handleResponse?: (response: Response) => boolean;
}): void;

Usage Example:

// client.tsx
import { initRealtimeClient } from 'rwsdk/realtime/client';

// Basic initialization
initRealtimeClient();

// With custom key
initRealtimeClient({
  key: 'dashboard',
  handleResponse: (response) => {
    console.log('Realtime update received');
    return true;
  },
});

Realtime Transport

Creates a custom transport for RSC that uses realtime WebSocket connection.

/**
 * Creates a realtime transport for RSC
 * @param options - Transport options
 * @returns Transport function
 */
function realtimeTransport(options?: {
  /** Realtime key for grouping */
  key?: string;
  /** Custom response handler */
  handleResponse?: (response: Response) => boolean;
}): Transport;

type Transport = (
  context: TransportContext
) => Promise<ReadableStream<Uint8Array>>;

Usage Example:

import { initClient } from 'rwsdk/client';
import { realtimeTransport } from 'rwsdk/realtime/client';

initClient({
  transport: realtimeTransport({ key: 'dashboard' }),
});

Realtime Durable Object

Durable Object class for managing realtime WebSocket connections and coordinating updates.

/**
 * Durable Object for realtime coordination
 */
class RealtimeDurableObject {
  /**
   * Creates a realtime Durable Object
   * @param state - Durable Object state
   * @param env - Environment bindings
   */
  constructor(state: DurableObjectState, env: any);

  /**
   * Handles HTTP requests and WebSocket upgrades
   * @param request - Incoming request
   * @returns Response or WebSocket upgrade
   */
  fetch(request: Request): Promise<Response>;

  /**
   * Handles incoming WebSocket messages
   * @param ws - WebSocket connection
   * @param data - Message data
   */
  webSocketMessage(ws: WebSocket, data: ArrayBuffer | string): void;

  /**
   * Handles WebSocket close events
   * @param ws - WebSocket connection
   */
  webSocketClose(ws: WebSocket): void;

  /**
   * Renders updates to connected clients
   * @param options - Rendering options
   */
  render(options?: {
    /** Specific client IDs to include */
    include?: string[];
    /** Specific client IDs to exclude */
    exclude?: string[];
  }): Promise<void>;
}

Usage Example:

import { RealtimeDurableObject } from 'rwsdk/realtime/durableObject';

// Export the Durable Object
export { RealtimeDurableObject };

// Configure in wrangler.toml:
// [[durable_objects.bindings]]
// name = "REALTIME_DO"
// class_name = "RealtimeDurableObject"
// script_name = "my-worker"

Complete Realtime Example

Worker Setup

// worker.tsx
import { defineApp, route, render } from 'rwsdk/worker';
import { realtimeRoute, renderRealtimeClients } from 'rwsdk/realtime/worker';

// Server function to update data and trigger realtime updates
async function updateCounter(env: any) {
  'use server';

  // Update counter in storage
  const count = await env.KV.get('counter') || 0;
  await env.KV.put('counter', count + 1);

  // Trigger realtime update for all clients
  await renderRealtimeClients({
    durableObjectNamespace: env.REALTIME_DO,
  });
}

function Counter() {
  'use client';
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => updateCounter()}>Increment</button>
    </div>
  );
}

function Document({ children }) {
  return (
    <html>
      <head>
        <title>Realtime App</title>
      </head>
      <body>{children}</body>
    </html>
  );
}

export default defineApp([
  // Add realtime route
  realtimeRoute((env) => env.REALTIME_DO),

  // Regular routes
  render(Document, [
    route('/', Counter),
  ]),
]);

// Export Durable Object
export { RealtimeDurableObject } from 'rwsdk/realtime/durableObject';

Client Setup

// client.tsx
import { initRealtimeClient } from 'rwsdk/realtime/client';

initRealtimeClient();

Wrangler Configuration

# wrangler.toml
name = "my-realtime-app"

[[durable_objects.bindings]]
name = "REALTIME_DO"
class_name = "RealtimeDurableObject"
script_name = "my-realtime-app"

Realtime Patterns

Broadcast Updates

// Broadcast to all clients
await renderRealtimeClients({
  durableObjectNamespace: env.REALTIME_DO,
});

Targeted Updates

// Send to specific users
await renderRealtimeClients({
  durableObjectNamespace: env.REALTIME_DO,
  include: ['user-123', 'user-456'],
});

Exclude Originator

// Update all except the client who made the change
async function handleUpdate(clientId: string, env: any) {
  await updateData();

  await renderRealtimeClients({
    durableObjectNamespace: env.REALTIME_DO,
    exclude: [clientId],
  });
}

Multiple Realtime Groups

// Client side - different keys for different features
initRealtimeClient({ key: 'chat' });
initRealtimeClient({ key: 'notifications' });

// Server side - target specific groups
await renderRealtimeClients({
  durableObjectNamespace: env.REALTIME_DO,
  key: 'chat', // Only clients listening to 'chat'
});