Architecture
Swarmbase composes several open-source subsystems into a coherent local-first stack. This page describes how the pieces fit together.
Package dependency graph
Section titled “Package dependency graph”@swarmbase/collabswarm (core)├── libp2p (peer-to-peer networking)├── Helia (content-addressed storage)├── @chainsafe/js-ipns (naming)├── BeeKEM (key encapsulation for dynamic groups)├── UCAN (authorization capabilities)└── @swarmbase/collabswarm-yjs / @swarmbase/collabswarm-automerge (CRDT adapters)
@swarmbase/collabswarm-react → @swarmbase/collabswarm@swarmbase/collabswarm-redux → @swarmbase/collabswarm@swarmbase/collabswarm-index → @swarmbase/collabswarmData flow: writing a change
Section titled “Data flow: writing a change”Application │ ▼document.change((state) => { state.getArray('items').push(['buy milk']) }) │ ▼CRDT Provider (Yjs / Automerge) │ applies mutation to local CRDT replica │ serializes the update ▼CollabswarmDocument │ wraps update in a signed CRDTChangeBlock │ encrypts block with document AES-GCM key │ addresses block by CID (SHA-256 hash of ciphertext) ▼Helia Blockstore (local IndexedDB) │ stores encrypted block ▼libp2p PubSub (GossipSub) │ publishes CID to document topic peers ▼Remote Peers │ receive CID announcement │ fetch encrypted block via libp2p bitswap / HTTP │ verify signature, decrypt, apply to local replica ▼CRDT convergesData flow: loading an existing document
Section titled “Data flow: loading an existing document”Application │ ▼document.open() │ ▼CollabswarmNode │ resolves document ID to CID via IPNS or bootstrap │ if local: loads frontier from Helia blockstore │ if remote: queries Q-of-K peers for frontier agreement ▼Load Quorum Orchestrator │ requests tips from configured bootstrap peers │ selects candidate with highest epoch │ waits for Q-of-K agreement before proceeding ▼Shadow Graph Walk │ walks CRDTChangeNode chain from frontier backward │ fetches missing blocks (bitswap / HTTP) │ verifies signatures, decrypts, applies to CRDT ▼Document is ready │ Mutations are now accepted via document.change() │ Reception of remote updates continues via GossipSubThe sync model
Section titled “The sync model”Swarmbase uses a shadow sync graph rather than a conventional Merkle-DAG:
- Each
document.change()call creates oneCRDTChangeBlock— an encrypted, signed, CID-addressed node containing a serialized CRDT update. - Each block references its parent(s) by CID, forming a DAG.
- New blocks are announced to peers via GossipSub (by CID, never by content).
- Peers fetch missing blocks on demand (bitswap or HTTP fetch).
- The CRDT layer resolves concurrent edits without a consensus leader.
This model is eventually consistent: local edits apply immediately, remote edits merge when they arrive. There is no global ordering, no server-assigned sequence number, and no single source of truth.
Peer-to-peer networking stack
Section titled “Peer-to-peer networking stack”┌─────────────────────────────────────┐│ Application │├─────────────────────────────────────┤│ CollabswarmNode ││ (document lifecycle, ACL, crypto) │├─────────────────────────────────────┤│ libp2p ││ ├── Transport layer ││ │ ├── WebSocket (relay, bootstrap)││ │ ├── WebRTC (browser-to-browser)││ │ └── WebTransport (modern) ││ ├── Stream Muxing (yamux/mplex) ││ ├── Connection Encryption (noise) ││ ├── Discovery ││ │ ├── Bootstrap list ││ │ ├── Kademlia DHT ││ │ └── AutoNAT ││ ├── NAT Traversal ││ │ ├── Circuit Relay v2 ││ │ ├── DCUtR (hole-punching) ││ │ └── STUN/TURN ││ └── PubSub ││ └── GossipSub (document topics)│├─────────────────────────────────────┤│ Helia / IPFS ││ ├── Blockstore (IndexedDB/local) ││ ├── Bitswap (block exchange) ││ └── IPNS (naming) │└─────────────────────────────────────┘Encryption and identity
Section titled “Encryption and identity”Application provides: ├── ECDSA P-384 signing key pair (writer identity) └── ECDH P-256 KEM key pair (key encapsulation)
CollabswarmNode manages: ├── Document AES-GCM keys (one per document, shared via BeeKEM) ├── Signing key → libp2p PeerId mapping (separate keys) └── ACL entries (reader/writer lists bound to signing public keys)
Per change: ├── Writer signs the CRDT update with their P-384 key ├── Payload is encrypted with the document's AES-GCM key ├── Signature is verified by receivers before decryption └── Encryption is transparent to the CRDT layerKey material never leaves the device in plaintext. Document keys are shared between authorized peers using BeeKEM — a key encapsulation mechanism that wraps the document key for each group member.
Where infrastructure is needed
Section titled “Where infrastructure is needed”Swarmbase documents can sync over peer-to-peer links, but most deployments need supporting infrastructure:
| Component | Required? | Purpose |
|---|---|---|
| Relay node | For browser peers | Bridges NAT; peers behind restrictive firewalls connect through it |
| Bootstrap node | For initial discovery | Provides a well-known entry point for the libp2p network |
| STUN/TURN server | For WebRTC direct connections | Helps peers establish direct browser-to-browser links |
| Remote pinning | Optional (integration incomplete) | Would persist encrypted blocks when all local peers go offline; the listener API exists but the current commit path does not invoke a publisher |
| Identity service | Application responsibility | Swarmbase does not provide user authentication or key management |
The relay server source is in relay-server/. The Docker Compose files in the repository root provide ready-to-run multi-node topologies for testing.
Current limitations
Section titled “Current limitations”See the limitations page for a complete list. Key architectural limitations to be aware of:
- No durable outbox: local blocks are stored in IndexedDB, but an unreachable peer may not receive the update; there is no delivery retry queue
- No automatic reconnect: the application must detect disconnection and re-establish transport
- No pass/fail performance budgets: benchmarks exist but have no thresholds
- Pinning is incomplete: the listener exists but the publisher does not
- Browser restart recovery is unverified: IndexedDB persistence works in tests but full close/reopen cycles are not proven in CI
Next steps
Section titled “Next steps”- Local-first design — what “local-first” means in Swarmbase
- CRDT model — how Yjs and Automerge integrate
- Networking — transports, discovery, and NAT traversal
- Security model — threat model, encryption, and ACL
- Storage — persistence, pinning, and recovery