Skip to content

Channels

Declare what flows in each direction between two runtimes — once.

A channel lists which actions flow in each direction between two apps. You write it once in shared code, and both sides use that same list — so neither side has to repeat itself or risk getting out of sync.

  • toAcceptor — actions the connector sends to the acceptor (a normal request: client asks, server answers).
  • toConnector — actions the acceptor pushes to the connector (the server calling the client). A domain can be in both lists if calls go both ways.
shared.ts
import { defineChannel } from "@nice-code/action";
export const appChannel = defineChannel({
toAcceptor: [act_user, act_lobby], // client → server requests
toConnector: [act_lobby], // server → client pushes (act_lobby goes both ways)
});

A channel holds two things: the routing (the toAcceptor / toConnector lists) and a compact binary format it uses to send actions over the wire, plus a version number worked out from your domains. Because both sides build all of this from the exact same definition, they can never disagree about the format or the version.

A channel only describes the actions and their format — never how a connection is secured. The same channel definition works whether the connection is plain or locked down, so you never have to think about that here. (When you’re ready, Security Levels shows how the same channel gains authenticated or encrypted connections.)

Both lists are optional. defineChannel({}) is a connection-only channel: no actions in either direction, but the connection it establishes is real — identity, security, and any frame protocols riding it. (A purely realm-only app doesn’t need even that: it opens the same connection with createWireClient, no channel at all — the two handshakes are interchangeable.)

The order of domains in each list is what builds that compact binary format, so the position of each one matters.

Always add new domains to the end of a list. If you reorder them, the version changes — and an out-of-date peer is cleanly rejected during the handshake instead of quietly sending things to the wrong place.

That’s the one rule to remember: add to the end, never reorder.