Skip to content

Introduction

Starfish is a transport-neutral realtime protocol designed for creative coding. It provides the building blocks for networked performance, multiplayer sketches, installations, live visuals, and distributed browser-based artworks.

Why Starfish?

Creative coding projects often need realtime communication between multiple participants — cursor sharing, synchronized visuals, collaborative drawing, live audio routing. Starfish gives you a simple, consistent API for all of these patterns without locking you into a specific language, runtime, or transport.

  • Sessions group participants together
  • Topics provide pub/sub messaging channels
  • Presence shares live state (cursor positions, tool selections, status)
  • Shared state persists key-value state across the session with conflict-free operations
  • WebRTC enables low-latency peer-to-peer communication when you need it

SDK Support

Starfish provides client SDKs for multiple languages with consistent APIs:

SDKPackageStatus
TypeScript@starfish/clientAvailable
PythonstarfishAvailable
SwiftStarfishClientAvailable

How It Works

A Starfish application connects to a server over WebSocket, joins a session, and communicates with other clients through topics, direct messages, or shared state. The SDK handles connection management, reconnection, clock synchronization, and transport selection automatically.

ts
import { StarfishClient } from "@starfish/client";

const client = new StarfishClient({ server: "ws://localhost:4000" });
await client.connect();
await client.join("my-session");

client.topics.publish("cursor", { x: 100, y: 200 });

client.topics.topic$("cursor").subscribe((frame) => {
  console.log(frame.header.from, frame.payload);
});
python
from starfish import StarfishClient, StarfishClientOptions

client = StarfishClient(StarfishClientOptions(server="ws://localhost:4000"))
await client.connect()
await client.join("my-session")

await client.publish("cursor", {"x": 100, "y": 200})

client.topic_stream("cursor").subscribe(
    lambda frame: print(frame.header.from_id, frame.payload)
)
swift
import StarfishClient

let client = StarfishClient(options: StarfishClientOptions(
    server: URL(string: "ws://localhost:4000")!
))
try await client.connect()
try await client.join(session: "my-session")

try client.topics.publish(topic: "cursor", payload: ["x": 100, "y": 200])

for await frame in client.topics.messages(forTopic: "cursor") {
    print(frame.header.from, frame.payload)
}

Guide Overview

PageWhat you'll learn
InstallationInstall the SDK and set up your environment
Quick StartBuild a minimal working example
Core ConceptsSessions, topics, presence, state, frames, and delivery
ConfigurationAll client options and how to tune them
API OverviewEvery method, observable, and type at a glance
ArchitectureHow connections, frames, transports, and reconnection work
Common WorkflowsPatterns for messaging, presence, shared state, and more
Best PracticesError handling, delivery tradeoffs, and resource cleanup
TroubleshootingCommon errors and how to fix them