Core Concepts
This documents the old v1 API. See Getting Started for the current version.
Zocket is built around a few key concepts that enable its type safety and developer experience.
Routers
Section titled “Routers”A Router is the contract between your server and client. It defines the structure of your WebSocket application. A router consists of two main parts:
Outgoing (.outgoing())
Section titled “Outgoing (.outgoing())”These are definitions of messages that the Server sends to the Client. You define the shape of the data using a schema (like Zod).
.outgoing({ chat: { message: z.object({ text: z.string(), from: z.string() }), typing: z.object({ userId: z.string(), isTyping: z.boolean() }) }})Incoming (.incoming())
Section titled “Incoming (.incoming())”These are handlers for messages that the Client sends to the Server. You define the input schema and the handler function.
.incoming(({ send }) => ({ chat: { sendMessage: zo.message .input(z.object({ text: z.string() })) .handle(({ ctx, input }) => { // Handle the message }) }}))Messages
Section titled “Messages”A Message (procedure) definition in the incoming router specifies:
- Input schema (optional): validates data sent by the client
- Middleware (optional): augments
ctxand/or blocks execution - Handler: runs when the message is received
zo.message .input(z.object({ roomId: z.string() })) .handle(({ ctx, input }) => { ctx.rooms.join(input.roomId); });Context
Section titled “Context”The Context (ctx) is an object that is available in every message handler. It is created when a client connects and persists for the duration of the connection.
const zo = zocket.create({ headers: z.object({ token: z.string() }), onConnect: (headers, clientId) => { const user = verifyToken(headers.token); return { user, db: getDbConnection() }; }});Built-in Context
Section titled “Built-in Context”ctx.clientId: The unique ID of the connected client.ctx.rooms: Room helpers (join,leave,has,current).
Middleware
Section titled “Middleware”Middleware allows you to wrap message handlers with common logic.
const requireUser = zo.message.use(({ ctx }) => { if (!ctx.user) throw new Error("Unauthorized"); return { user: ctx.user };});JSON payloads
Section titled “JSON payloads”Zocket’s transport is JSON. Prefer JSON-friendly types (strings, numbers, booleans, objects, arrays).