Skip to main content

Client SDK

Beta

This feature is in beta. Core behavior is stable and ready to try, but some APIs or configuration may still evolve before general availability.

In v2 all state mutations happen server-side -- clients can only read state and send actions. The server mutates state in response to actions via handlers.actions.

On the newer Room SDKs, the preferred public shape is a unified namespace surface with four core live capabilities:

  • room.state

  • room.meta

  • room.members

  • room.signals Two companion namespaces round out the client runtime:

  • room.admin

  • room.session

Legacy flat methods such as room.send(...), room.getSharedState(), and room.onMessage(...) still exist for compatibility. Prefer the unified namespaces when your SDK supports them. See SDK Support.

Unified Namespace Availability

The unified namespace surface is available across the JavaScript/TypeScript, Dart, Swift, Kotlin, and Java Room SDKs. Method names and casing follow each platform's conventions.

Legacy flat methods still exist as compatibility fallbacks, so older examples and the mapping tables below may still show room.send(...), room.getSharedState(), and related APIs.

Installation

npm install @edge-base/web
# React Native:
npm install @edge-base/react-native

Connect

Rooms are identified by a namespace and a room ID. Ensure the user is authenticated before connecting.

import { createClient } from '@edge-base/web';
// React Native: import { createClient } from '@edge-base/react-native';

const client = createClient('https://your-project.edgebase.fun');
// ... authenticate first ...

const room = client.room('game', 'lobby-1');
await room.join();

To leave:

room.leave();

Pre-Join Helpers

The JavaScript/TypeScript web SDK exposes HTTP helpers for lobby UIs and connection diagnostics before you call room.join().

const summary = await client.getRoomSummary('game', 'lobby-1');
console.log(summary.metadata, summary.occupancy.activeMembers);

const summaries = await client.getRoomSummaries('game', ['lobby-1', 'lobby-2']);
console.log(summaries.items.map((item) => item.roomId));

const readiness = await client.checkRoomConnection('game', 'lobby-1');
if (!readiness.ok) {
console.warn(readiness.message);
}

const room = client.room('game', 'lobby-1');
const roomSummary = await room.meta.summary();
const roomReadiness = await room.checkConnection();

Use these helpers when you want to:

  • render room cards before join
  • show occupancy in a lobby list
  • validate room runtime configuration before opening a WebSocket
  • explain why room connection preflight would fail before opening a live session

Unified Surface

The unified Room surface groups the product around the same live-session model used in the newer SDK implementations.

NamespacePurpose
room.stateAuthoritative commands plus shared / private state reads and subscriptions
room.metaPublic-safe metadata before or after joining
room.membersPresence list, member join/leave events, and ephemeral member state
room.signalsFire-and-forget room events and direct member sends
room.adminModeration controls like kick, block, and role changes
room.sessionErrors, reconnects, kicked events, and connection state
const room = client.room('game', 'lobby-1');
await room.join();

const meta = await room.meta.get();

room.state.onSharedChange((state) => renderBoard(state));
room.members.onSync((members) => renderRoster(members));
room.signals.on('chat.message', (payload) => appendChat(payload));
room.session.onConnectionStateChange((state) => console.log('room state:', state));

await room.state.send('MOVE', { to: { x: 5, y: 3 } });
await room.signals.send('chat.message', { text: 'hello' });

The rest of this page keeps the flat compatibility methods documented because they are still useful as cross-SDK fallbacks and map cleanly to the unified namespaces.

Preferred namespace APICompatibility API
room.state.getShared()room.getSharedState()
room.state.getMine()room.getPlayerState()
room.state.onSharedChange(...)room.onSharedState(...)
room.state.onMineChange(...)room.onPlayerState(...)
room.state.send(...)room.send(...)
room.meta.get()room.getMetadata()
room.meta.summary()room.getSummary()
room.signals.on(...) / room.signals.onAny(...)room.onMessage(...) / room.onAnyMessage(...)
room.session.onError(...) / room.session.onKicked(...)room.onError(...) / room.onKicked(...)

Read State

v2 has two separate state areas:

  • Shared state -- visible to all players in the room.
  • Player state -- private to each individual player.

Both are read-only on the client.

const shared = room.state.getShared();
const player = room.state.getMine();

Subscribe to State Changes

Shared State

Called on initial sync and whenever the shared state changes. The handler receives the full state and only the changed fields (delta).

const sub = room.state.onSharedChange((state, changes) => {
console.log('Shared state:', state);
console.log('Changes:', changes);
renderGame(state);
});

// Later: stop listening
sub.unsubscribe();

Player State

Called on initial sync and whenever the player's own state changes.

const sub = room.state.onMineChange((state, changes) => {
console.log('Player state:', state);
updateInventory(state);
});

sub.unsubscribe();

Send Actions

Actions are sent to the server's handlers.actions entries and return the server's result.

const result = await room.state.send('MOVE', { to: { x: 5, y: 3 } });
console.log('Move result:', result);

If the action fails server-side, the Promise rejects:

try {
await room.state.send('ATTACK', { target: 'player-2' });
} catch (err) {
console.error('Action failed:', err.message);
}

Signals and Legacy Messages

On unified clients, prefer room.signals.on(...), room.signals.onAny(...), room.signals.send(...), and room.signals.sendTo(...).

The flat room.onMessage(...) and room.onAnyMessage(...) APIs below remain documented as compatibility wrappers for server-sent messages from room.sendMessage() or room.sendMessageTo() in server-side code.

// Listen for a specific signal event
const sub = room.signals.on('game_over', (data) => {
console.log('Winner:', data.winner);
});

sub.unsubscribe();

Listen for all messages regardless of type:

const sub = room.signals.onAny((event, data) => {
console.log(`Signal [${event}]:`, data);
});

sub.unsubscribe();

-> Server-side message sending: Server Guide


Kicked

The server can kick a player. After being kicked, auto-reconnect is disabled. On the unified surface, this lives under room.session.onKicked(...).

room.session.onKicked(() => {
console.log('You were kicked from the room');
showKickedUI();
});

-> Server-side kick setup: Server Guide


Error Handling

On the unified surface, error handling lives under room.session.onError(...).

room.session.onError((err) => {
console.error(`Room error [${err.code}]: ${err.message}`);
});

Auto-Reconnect

Built-in with exponential backoff. If the WebSocket drops, the SDK automatically reconnects, re-authenticates, and replays the latest room state. On the unified surface, room.session.onReconnect(...) and room.session.onConnectionStateChange(...) are the primary lifecycle hooks.

Configure via options:

const room = client.room('game', 'lobby-1', {
autoReconnect: true, // default: true
maxReconnectAttempts: 10, // default: 10
reconnectBaseDelay: 1000, // default: 1000ms
sendTimeout: 10000, // default: 10000ms
});

React Native: Works transparently across app foreground/background transitions.

room.session.onReconnect(({ attempt }) => {
console.log('reconnecting attempt', attempt);
});

room.session.onConnectionStateChange((state) => {
console.log('connection state', state);
});

Unified Surface Reference

The unified Room namespaces are currently implemented in the SDKs listed on SDK Support. Use this as the primary mental model when building new Room features.

NamespaceRepresentative APIs
room.stategetShared(), getMine(), onSharedChange(), onMineChange(), send()
room.metaget()
room.memberslist(), onSync(), onJoin(), onLeave(), setState(), clearState(), onStateChange()
room.signalssend(), sendTo(), on(), onAny()
room.adminkick(), block(), setRole()
room.sessiononError(), onKicked(), onReconnect(), onConnectionStateChange()

Compatibility API Reference

The tabbed tables below keep the flat compatibility methods that are still widely available across SDKs and older examples.

Method / PropertyTypeDescription
client.room(namespace, roomId, options?)RoomClientCreate a room client
room.join()Promise<void>Connect, authenticate, and join
room.leave()voidDisconnect and clean up
room.getSharedState()Record<string, unknown>Get current shared state snapshot
room.getPlayerState()Record<string, unknown>Get current player state snapshot
room.send(actionType, payload?)Promise<unknown>Send action to server, returns result
room.onSharedState(handler)SubscriptionShared state changes -- returns { unsubscribe() }
room.onPlayerState(handler)SubscriptionPlayer state changes -- returns { unsubscribe() }
room.onMessage(type, handler)SubscriptionServer message by type -- returns { unsubscribe() }
room.onAnyMessage(handler)SubscriptionAll server messages -- returns { unsubscribe() }
room.onError(handler)SubscriptionError occurred -- returns { unsubscribe() }
room.onKicked(handler)SubscriptionKicked from room -- returns { unsubscribe() }
room.namespacestringRoom namespace
room.roomIdstringRoom instance ID