P2P Chat Example
A fully decentralized peer-to-peer chat application demonstrating the complete toolkit-p2p stack.
Features
- 🔐 Cryptographic Identity - Each user has a unique Ed25519 keypair
- 🌐 WebRTC Transport - Direct peer-to-peer connections
- 📦 Content-Addressed Storage - SHA-256 based message storage
- 🔄 CRDT Synchronization - Conflict-free message ordering with LWW-Map
- 🎨 Beautiful UI - Modern, responsive chat interface
Architecture
User A User B
├─ Identity (Ed25519) ├─ Identity (Ed25519)
├─ WebRTC Transport ├─ WebRTC Transport
├─ Mesh Cache (SHA-256) ├─ Mesh Cache (SHA-256)
└─ LWW-Map CRDT └─ LWW-Map CRDT
│ │
└──────── Sync via Merkle Trees ──────┘
How It Works
1. Identity Management
Each peer generates an Ed25519 keypair for signing messages and establishing trust.
2. Message Storage
Messages are stored in a Last-Writer-Wins Map (LWW-Map) CRDT:
- Each message has a vector clock timestamp
- Concurrent edits are resolved deterministically
- Deletions use tombstones
3. Synchronization
- Merkle trees detect differences between peers
- Only changed messages are transmitted
- Efficient bandwidth usage
4. Conflict Resolution
When two peers send messages simultaneously:
- Vector clocks detect the concurrent write
- Peer IDs provide deterministic tie-breaking
- Both messages are preserved in correct order
Running the Example
pnpm install
pnpm dev
Usage
- Enter your name - This becomes your display name
- Enter room code (optional) - Leave empty to create a new room
- Click "Join Chat" - Connects to peers in the same room
- Start chatting - Messages sync automatically via CRDTs
Code Structure
src/
└── main.ts # Main application logic
├── Identity setup
├── CRDT initialization
├── Transport setup
├── Message handling
└── UI rendering
Integration Points
@toolkit-p2p/identity
const identity = await generateIdentity();
@toolkit-p2p/sync
const messages = createLWWMap<string, Message>();
let clock = increment(clock, peerId);
messages = set(messages, msgId, message, clock, peerId);
messages = merge(localMessages, remoteMessages);
@toolkit-p2p/mesh-cache
const cache = new MeshCache({ transport });
await cache.init();
const cid = await cache.put(messageData);
const data = await cache.get(cid);
@toolkit-p2p/transport
const transport = createTransport({
identity,
signalingUrl: 'ws://localhost:8080',
roomCode,
});
transport.broadcast(message);
transport.onMessage((peerId, data) => {
});
CRDT Guarantees
This chat application guarantees:
✅ Eventual Consistency - All peers converge to the same message history
✅ Commutativity - Message order is deterministic regardless of delivery order
✅ Idempotency - Receiving the same message multiple times has no effect
✅ Partition Tolerance - Works offline, syncs when reconnected
Performance
| Send message | O(1) | Instant local update |
| Receive message | O(1) | CRDT merge operation |
| Sync messages | O(log n) | Merkle tree comparison |
| Full sync | O(n) | Only on first connect |
Extending
Want to add more features? Try:
- Typing indicators - Using G-Counter CRDT
- Read receipts - Using LWW-Map per message
- File sharing - Using content-addressed storage
- Reactions - Using OR-Set CRDT
- Channels - Multiple LWW-Map instances
Learn More
License
MIT