Appearance
P2P Quick Start
Get peer-to-peer shared data working in 3 steps.
Prerequisites
- Pulse server running with P2P enabled in the environment config
- A publishable key (
pk_) and user token
Enable P2P
P2P is disabled by default. Enable it from the Admin Panel → Environment Settings → P2P / Real-time Data → toggle "Enable P2P data channels".
1. Connect with P2P Enabled
Using the Widget
html
<pulse-widget
api-key="pk_..."
token="eyJ..."
room="my-board"
endpoint="wss://pulse.example.com"
p2p="true"
></pulse-widget>Using the Client SDK
typescript
import { PulseClient } from '@gamention/pulse-core';
const client = new PulseClient({
apiKey: 'pk_...',
token: userToken,
room: 'my-board',
endpoint: 'wss://pulse.example.com',
p2p: true,
});
client.connect();| Option | Type | Default | Description |
|---|---|---|---|
p2p | boolean | false | Enable P2P data channels |
iceServers | RTCIceServer[] | Google STUN | Custom STUN/TURN servers |
TURN Credentials
If your environment has a TURN server configured in the admin panel, the SDK automatically fetches time-limited credentials from the server. You don't need to pass iceServers manually.
2. Access the P2P Manager
The P2P module is lazy-loaded — it only downloads when you first access it. This keeps the base SDK lightweight.
typescript
const p2p = await client.p2p;This returns a P2PManager instance after:
- Waiting for authentication to complete
- Loading the P2P module (Yjs + WebRTC code)
- Fetching TURN credentials (if configured)
- Bootstrapping persisted state from the server
3. Create Shared Data
typescript
const p2p = await client.p2p;
// Create shared data structures
const board = p2p.sharedMap('kanban');
const taskOrder = p2p.sharedList('task-order');
const likes = p2p.sharedCounter('likes');
// Set data — syncs to all peers instantly
board.set('task-1', { title: 'Design homepage', column: 'doing' });
taskOrder.push('task-1');
likes.increment();
// Listen for changes (local or remote)
board.on('change', (changes) => {
for (const change of changes) {
console.log(`${change.action}: ${change.key}`, change.value);
}
});That's it. Any user in the same room with P2P enabled will see the same data, updated in real-time.
Full Example: Collaborative Counter
A minimal example — two users increment a counter and see updates instantly:
typescript
import { PulseClient } from '@gamention/pulse-core';
const client = new PulseClient({
apiKey: 'pk_...',
token: userToken,
room: 'counter-demo',
endpoint: 'wss://pulse.example.com',
p2p: true,
});
client.connect();
const p2p = await client.p2p;
const counter = p2p.sharedCounter('votes');
// Display current value
document.getElementById('count').textContent = counter.value;
// Update on changes from any peer
counter.on('change', (value) => {
document.getElementById('count').textContent = value;
});
// Increment on button click
document.getElementById('vote-btn').addEventListener('click', () => {
counter.increment();
});What Happens Under the Hood
client.connect()— opens a WebSocket to the Pulse server, authenticatesclient.p2p— lazy-loads the P2P module, bootstraps persisted state- WebRTC peer connections are established with other users in the room
sharedMap/sharedList/sharedCounter— creates Yjs-backed data structures- Mutations sync via P2P DataChannels (or WebSocket fallback if P2P unavailable)
- State auto-persists to the server every 5 seconds
Next Steps
- Shared Data Structures — Full API reference for SharedMap, SharedList, SharedCounter
- Raw Channels & Connection Info — Custom peer-to-peer messaging
- Environment Config — P2P settings (mesh limit, persist interval, etc.)