Skip to main content

JavaScript SDK — @metered-ca/peer

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/peer

~10 KB gzipped for pub/sub-only use, ~30 KB combined with WebRTC. ESM + CJS + UMD bundles. Zero runtime dependencies — everything else comes from the browser (or Node 22+).

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 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.