Skip to main content
This page covers Realtime V2. Legacy Realtime uses a different connection route and protocol; see Realtime (Legacy).

Prerequisites

  • A realtime server, such as chat from Servers & Channels. This guide creates a separate demo channel on it.
  • The server’s canonical, copied from its settings or pulled XanoScript. Script references use the server name; the client URL uses the canonical.
  • An instance with the V2 WebSocket service and /ws/ route enabled.
  • An application user JWT only if you configure the demo channel or handler to require authentication.

Connection address

The example address is illustrative; use your own instance and preserved server canonical. /ws/ targets V2. /rt/ targets legacy Realtime.

Create a demo channel

Create this channel on the chat server. It allows anonymous test clients and uses at_most_once delivery:
XanoScript
The minimal client below does not implement acknowledgement or replay handling for at_least_once. Use this demo channel instead of pointing it at a channel configured for durable delivery. For application use, choose access rules appropriate to your users.

Create an echo handler

Create this message on the chat server’s demo/{room_id} channel:
XanoScript
The response goes only to the invoking client. Changing deliver_to to channel broadcasts the response to the subscribed clients; others excludes the sender.

Connect and join

Save this module as socket.js. It sends a join request after opening, retries only the initial Connection is not ready error, and resolves ready only after the join acknowledgement. Other errors are surfaced rather than retried indefinitely.
socket.js
Import it from your frontend module and substitute your own connection address:
The demo channel allows anonymous access, so this call omits token. For an authenticated channel, add token: userJwt to the options using a token obtained from your application login flow. For a component-based application, also call client.close() during component teardown. The echo arrives as action: "message", type: "echo", with the body and session in payload. A socket’s open event alone is not a join acknowledgement, and a broadcast receipt is not a delivered message.

Wire frames

The invocation’s type selects the named message handler; payload supplies its inputs. Use the resolved channel path (demo/42), not the declaration template (demo/{room_id}). Keep type at the top level of the frame.

Authentication

The module passes an application user JWT as the WebSocket subprotocol, equivalent to:
This is a user token from an auth-enabled table, not an administrative Metadata API token. Never put the CLI’s administrative token in frontend code. Message-level authentication and channel join authorization are described in Access Control.

Verify delivery

  1. Open two independent clients and wait for both join acknowledgements.
  2. Invoke a message with deliver_to = "channel"; verify that both clients receive its response.
  3. Invoke the echo handler above; verify that only its sender receives it.
  4. Publish from an API using realtime.publish and verify the incoming message frames on the subscribed clients.
Do not treat a successful import, an HTTP publish response, or a broadcast receipt as proof that a recipient received a message.

Troubleshooting

Next steps

Messages

Define payloads and choose who receives the result.

Realtime Triggers

Use the complete join authorization example.