Skip to main content

Client SDK

Beta

This feature is in beta. Core behavior is stable, but some APIs or configuration may change 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 five core live capabilities:

  • room.state
  • room.meta
  • room.members
  • room.signals
  • room.media (alpha)

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.

Non-JS SDK Surface

The unified namespace (room.state.*, room.members.*, etc.) is currently available in the JavaScript/TypeScript SDK. Non-JS SDKs (Dart, Swift, Kotlin, Java, C#, C++) currently use the flat API surface shown in the compatibility tables below.

Installation

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

Connect

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

import { createClient } from '@edgebase/web';
// React Native: import { createClient } from '@edgebase/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();

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.media (alpha)Audio/video/screen publish, mute, device, and track state
room.adminModeration controls like kick, mute, disable video, 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.media.onTrack((track, member) => attachTrack(track, member));
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.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.media (alpha)list(), audio.enable(), audio.setMuted(), video.enable(), screen.start(), devices.switch(), onTrack()
room.adminkick(), mute(), block(), setRole(), disableVideo(), stopScreenShare()
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