Getting started
Introduction
Dendri adds realtime collaboration to any web app (presence, live cursors, chat, video, and CRDT document sync) using peer-to-peer WebRTC instead of a message broker you pay per event.
What is Dendri?
Dendri is a small signaling service plus a TypeScript SDK. The server's only job is to introduce peers to each other and broker the WebRTC handshake. Once two browsers are connected, data flows directly between them: the server is out of the data path, which is why there is no per-message billing and no realtime backend for you to scale.
The project ships as three parts:
| Package | Version | License | What it is |
|---|---|---|---|
@afterrealism/dendri-client |
2.6.x | Apache-2.0 | Framework-neutral browser/Node SDK: rooms, presence, topics, RPC, media calls, and adapters for React, Vue, and Svelte. |
@afterrealism/dendri-y |
0.1.x | Apache-2.0 | Yjs CRDT provider that syncs a Y.Doc (and awareness) over a Dendri room. |
dendri-server |
Rust | AGPL-3.0 | Axum/Tokio signaling server with WebSocket, SSE, and long-poll transports, TURN credential minting, and an optional encrypted relay. |
How it works
When your app calls join("room-name"), the SDK connects to the signaling server,
discovers the other peers in the room, and negotiates direct WebRTC connections with them. Rooms
use a star topology: the first peer to join becomes the host, later
peers connect to the host, and if the host disconnects a deterministic election promotes a new
one (host migration), no coordination service required.
Real networks are hostile, so connectivity degrades through four tiers automatically:
| Tier | Path | When it's used |
|---|---|---|
| 1 | Direct P2P | Same network, or open NAT. Lowest latency, zero server involvement. |
| 2 | STUN | Peers behind NAT discover their public addresses and hole-punch. |
| 3 | TURN | Symmetric NAT or UDP blocked; traffic relays through a TURN server (e.g. coturn). |
| 4 | TLS relay | Everything else (strict VPNs, corporate proxies); messages relay through the signaling server, end-to-end encrypted with ECDH + AES-256-GCM so the server can't read them. |
The signaling connection itself also falls back: WebSocket first, then Server-Sent Events, then HTTP long-poll, so the handshake works even behind proxies that kill WebSockets.
Core concepts
Peers
A Dendri instance is one peer: a stable identity (peer ID) plus a signaling
connection. Peers open data connections to exchange arbitrary payloads and
media connections for audio/video. You rarely manage peers by hand (rooms and
the store do it for you), but the low-level API is always available.
Rooms
A Room groups peers under a shared name and manages the star topology, peer
discovery, reconnection, and host migration. Everything higher-level (presence, topics, RPC)
hangs off a room.
Presence
Each peer can publish a small state object ("Ana, editing slide 3, cursor at…") that is broadcast to the room and kept in sync. Presence answers "who's here and what are they doing" without you building any plumbing.
Topics
Pub/sub channels inside a room. Broadcast with a topic tag and only subscribers to
that topic receive it, so chat messages, cursor updates, and game state can share one room
without interfering.
RPC
Request/response over data channels. Register a named method on one peer, call it from another, and get a promise back, with timeouts and typed errors. Useful for host-authoritative logic in games and tools.
The store
createDendriStore() wraps a room in a framework-agnostic reactive store
(subscribe / getSnapshot), with ready-made bindings for React, Vue, and
Svelte. It's the recommended entry point for UI apps; see the
framework guides.
Explore the docs
Quickstart
Run a server, install the SDK, and ship a working P2P chat in about ten minutes.
Configuration
Every client option: URLs, transports, TURN, relay, JWT auth, and debugging.
Framework guides
Complete React, Vue, Svelte, and vanilla JS integrations with the official adapters.
Building the examples
Walkthroughs of chat, live cursors, presence, whiteboard, video, files, and a game.
Collaborative editing
Sync Yjs documents and awareness over a room with @afterrealism/dendri-y.
API reference
Classes, methods, events, and types for the client SDK and the Yjs provider.
Self-hosting
Run the open-source Rust server with Docker/Podman, TLS, TURN, and Redis.
AI & agents
llms.txt, markdown docs, and the MCP server for Claude Code, opencode, Cursor, and VS Code.
Licensing at a glance
The client SDKs (dendri-client, dendri-y) are
Apache-2.0: embed them in anything, commercial or not. The signaling server is
AGPL-3.0: run it freely, but if you offer it as a network service with
modifications, you must publish those modifications. A commercial license is available from
Afterrealism for closed-source hosted use. Details in
Self-hosting → Licensing.
Something missing? Open an issue on GitHub.