Skip to content

Apps

An App bundles one or more actor definitions into a single object that the server, client, and React packages can consume.

import { createApp } from "@zocket/core";
import { ChatRoom } from "./chat";
import { GameMatch } from "./game";
export const app = createApp({
actors: {
chat: ChatRoom,
game: GameMatch,
},
});

The keys you choose (chat, game) become the actor names used everywhere:

  • Server — the handler routes RPC calls to the correct actor by name
  • Clientclient.chat("room-1") returns a typed handle for the chat actor
  • ReactuseActor("chat", "room-1") uses the same name

The AppDef type carries the full type information of all registered actors. Pass typeof app as a generic to the client and React factories:

import { createClient } from "@zocket/client";
import type { app } from "./server";
// Full type inference — no manual types needed
const client = createClient<typeof app>({ url: "ws://localhost:3000" });
const room = client.chat("general");
// ^? ActorHandle with sendMessage, on("newMessage"), state, etc.

The returned object has this shape:

interface AppDef<TActors> {
readonly _tag: "AppDef";
readonly actors: TActors; // Record<string, ActorDef>
}

The _tag discriminant is used internally for type narrowing. You generally don’t need to interact with it directly.

setup() is an alias for createApp() with different naming, used when registering actors for the distributed runtime (docker-compose deployment with gateway + NATS + runtime):

import { setup } from "@zocket/core";
import { counter } from "./actors/counter";
import { chat } from "./actors/chat";
export const registry = setup({ use: { counter, chat } });

The returned object is the same AppDef — the only difference is the naming convention (use instead of actors). Use createApp() for standalone mode and setup() for the distributed runtime.

  • Use camelCase for actor names: chat, gameMatch, drawingRoom
  • Each name must be unique within an app
  • The name is used as-is in the wire protocol ({ actor: "chat", actorId: "room-1" })