What to build with BridgeSwarm

Every example below runs on the bundled demos server. Install BridgeSwarm, enable Examples server in Settings, and open http://127.0.0.1:4173/ in two tabs.

01

P2P chat rooms

A topic is a room. Everyone who joins the same topic string finds each other through Hyperswarm and exchanges messages over direct, Noise-encrypted connections — no chat server, no message broker, no accounts.

The chat example is a minimal single-file room: join a topic, broadcast text, render an inbox. chat-advanced builds rooms, presence, markdown rendering, emoji, and peer-to-peer file sharing on the same primitives.

const swarm = new BridgeSwarm({ appName: 'chat-demo' });
await swarm.join('room:general');
swarm.on('connection', (conn, peerInfo) => {
  conn.on('data', (data) => render(peerInfo.publicKey, data));
});
function broadcast(text) {
  for (const conn of swarm.connections()) conn.write(text);
}
02

Collaborative apps

Anything that broadcasts small structured events to everyone in a session — cursors, strokes, edits — maps directly onto swarm connections. The whiteboard example is a shared canvas where every stroke is written to every connected peer as it happens.

For richer protocols than "write JSON, parse JSON," attach Protomux to the connection and define named message channels instead of hand-rolling a dispatch table.

swarm.on('connection', (conn) => {
  conn.on('data', (buf) => applyRemoteStroke(JSON.parse(buf)));
});
canvas.addEventListener('pointermove', (e) => {
  const stroke = strokeFrom(e);
  for (const conn of swarm.connections()) conn.write(JSON.stringify(stroke));
});
03

Data sync

When you don't want to hand-roll message protocols at all, let the host replicate structured storage directly. swarm.setAutoReplicate({ swarmId, enabled: true }) takes over every new connection on a swarm for Hypercore replication — those sockets stop forwarding raw data to the page and instead keep a Hypercore (or Hyperbee/Hyperdrive built on one) in sync across every peer automatically.

The data-demo example exercises Hyperbee, Hyperdrive, and Hyperdb directly through BridgeSwarm.request; sync-demo shows the auto-replicate path end to end.

await BridgeSwarm.request('beePut', { key: 'title', value: 'Q3 plan' });
const doc = await BridgeSwarm.request('beeGet', { key: 'title' });

await swarm.setAutoReplicate({ enabled: true }); // new connections auto-sync
04

Live media

The host's media capability pack wraps bare-ffmpeg for real encode work, including a live session mode: push captured frames in, get VP9/WebM segments out — to a Media Source Extensions player on the page, fanned out to swarm peers, or archived to disk, in any combination.

const live = BridgeSwarm.media.liveSession(videoEl);
await live.start({ width: 640, height: 360, fps: 10, ingest: 'frames' });
await live.pushFrame(canvas);
await live.subscribe({ swarm: { connIds: [conn.connId] } }); // fan out to a peer
await live.stop();

See live-encode for the host-encode → MSE pipeline, media-demo for batch probe/transform/transcode, and clip-studio for nearline recording workflows.

05

Self-hosted web apps

The bundled demos server is itself proof of a pattern worth building on: the Bare host can run a small bare-http1 static server on 127.0.0.1 and serve a full HTML/CSS/JS app with no cloud hosting step. Because the content script injects window.BridgeSwarm into pages served from real HTTP origins (not file://), an app served this way gets P2P networking for free — it's a normal page as far as the browser is concerned.

This is the same mechanism the extension itself uses: toggle Examples server in Settings and the host starts serving on 127.0.0.1:4173 with no separate deploy step.

// extension -> host, on settings change
examplesServer.start({ host: '127.0.0.1', port: 4173 })
// host responds
{ running: true, url: 'http://127.0.0.1:4173/' }
06

Live topic domains

A DNS name is a static pointer maintained by infrastructure you rent. A Hyperswarm topic behaves more like an address you dial directly — whoever is currently announcing it is reachable, for as long as they keep at least one connection to the DHT. Nothing to register, nothing to renew, no hosting bill if nobody's listening.

You can lean on this directly: derive a topic from a room name, an invite code, or a content hash, and treat "join this topic" as the entire addressing scheme for a feature. The chat and whiteboard examples both do exactly this — the topic string is the room.

const topic = await sha256(`my-app:${roomSlug}`);
await swarm.join(topic); // this room now "exists" for as long as someone's in it
07

Firewall-controlled rooms

Discovery is open by design — that's the point of a DHT — but connections don't have to be. swarm.setFirewall({ mode, keys }) switches a swarm between off, allowlist, and denylist modes keyed on peer public keys, and swarm.ban(publicKey) / peerInfo.ban() drops a specific peer outright.

await swarm.setFirewall({ mode: 'allowlist', keys: [trustedKeyHex] });

swarm.on('connection', (conn, peerInfo) => {
  if (isSpamming(peerInfo)) peerInfo.ban();
});

The firewall-room example wires this up as a live allowlist/denylist/ban UI you can test against a second tab.

08

Developer tooling

Two building blocks for anyone shipping a protocol on top of BridgeSwarm rather than a demo app: Protomux for hand-designed message channels in the page, and HRPC for schema-defined, streaming RPC on the host.

// HRPC: unary + streaming from the page
await BridgeSwarm.request('attachHrpc', { connId: conn.connId });
const pong = await swarm.hrpcCall(conn.connId, 'ping', { value: 'hi' });
await swarm.hrpcCall(conn.connId, 'fetchStream', { count: 3 }, {
  onChunk: (c) => console.log(c),
});

sdk-demo exercises swarm lifecycle and raw Protomux; hrpc-demo covers unary calls and both streaming directions end to end.

Pick one and go build it

Every demo above is source-available in the repo's examples/ directory as a starting point.