Skip to main content

JavaScript SDK — @metered-ca/realtime

The official browser + Node SDK for Metered Realtime Messaging. Speaks the same wire protocol as the raw WebSocket path, with the framing, reconnection, ack correlation, presence diffing, perfect-negotiation WebRTC, and TURN credential injection done for you.

npm install @metered-ca/realtime

ESM + CJS + UMD bundles; the full UMD is ~13 KB gzipped (WebRTC included), within a 30 KB budget. Zero runtime dependencies — everything else comes from the browser (or Node 22+). It also runs on React Native via react-native-webrtc.

Pick your path​

The SDK ships two public classes. Pick by what you're building:

You're building…UseWhy
WebRTC video / voice call, screen share, peer-to-peer gameMeteredPeerJoins a channel, discovers peers via presence, manages each RTCPeerConnection for you, fans MediaStreams out automatically, recovers ICE on network changes
Live chat with presence, classroom roster, multiplayer lobbyMeteredPeerThe peer-joined / peer-left events drive your UI; peer.send(data) broadcasts or directs
IoT telemetry, MQTT-style pub/sub, AI agent message bus, collaborative cursorsSignallingClientPub/sub + directed messages without the WebRTC overhead. Smaller, simpler, multiple channels per connection

Not sure? Start with MeteredPeer. Drop down to SignallingClient later if you find you don't need the channel-+-peer model.

What the SDK does for you​

These are the things you'd write yourself if you used the raw WebSocket path — the SDK handles them:

  • Framing + ack correlation — every subscribe, publish, send resolves a promise when the server acks
  • Auto-reconnect with exponential backoff, jitter, and close-code-aware behaviour (terminal codes stop retrying, rate-limit codes slow-backoff, etc.)
  • Token refresh — your tokenProvider is re-invoked on every reconnect so JWT-rotated TURN creds + permissions land automatically
  • Inactivity watchdog — if the server stops sending frames, the SDK closes-and-reconnects instead of leaving you on a half-dead socket
  • Presence diff — translates raw presence events into per-peer peer-joined / peer-left so your UI doesn't have to diff rosters
  • Perfect negotiation — automatic SDP + ICE handling with a tie-breaker that prevents glare
  • ICE-restart ladder — 9 retries spanning ~121 s for WebRTC-level recovery (Wi-Fi → cellular roam, TURN failover)
  • Channel-level reconcile — when the signalling socket drops, your RemotePeer references survive the reconnect; only the underlying RTCPeerConnection is swapped (see Reconnect Best Practices)

What your code still owns​

The SDK does not silently make decisions on your behalf for things that affect UX or billing. You still own:

  • Auth mode + token minting — see Authentication
  • Reconnect UI — the SDK fires state-change events; how (or whether) you surface a "reconnecting…" banner is up to you. See Reconnect Best Practices for the standard patterns
  • Token expiry handling — if your tokenProvider keeps failing, the SDK fires a token-provider-error event after 3 consecutive failures. Show a "please log in again" prompt
  • DataChannel reopening — if you use the remote.pc.createDataChannel(...) escape hatch for P2P data, those handles don't survive a reconnect. See Data Channels & Low Latency
  • Channel naming + JWT claims — your backend decides who can subscribe to what; the SDK enforces what the server tells it

Where to start​

If you want to…Go here
Get something running in 5 minutesGetting Started
Build a WebRTC video callGuide: WebRTC Video Call
Build a video call from a static site with no backendGuide: WebRTC No Backend
Build a React Native mobile appGuide: React Native
Build chat / presence / a lobbyGuide: Presence & Chat
Wire up AI agentsGuide: AI Agent Communication
Pipe IoT telemetryGuide: IoT Telemetry
Handle reconnects properly (production-grade)Guide: Reconnect Best Practices
Port from simple-peer / PeerJSMigration: from simple-peer · from PeerJS
Look up a method / eventAPI Reference: MeteredPeer · SignallingClient

Or — use the raw WebSocket path​

The SDK is the recommended path for JavaScript + TypeScript apps. If you're on a stack the SDK doesn't cover (Go, Python, Java, Swift, Kotlin, Rust, Unity/C#, etc.), implement the protocol directly. Everything the SDK does on top of the wire is documented in the Protocol Reference and the Use Case Guides show end-to-end raw-WS code for the same scenarios.

The SDK speaks the same protocol byte-for-byte. You can mix and match — an SDK client and a raw-WS client can be peers in the same channel.