P2P collaborative document sync built on Yjs, WebRTC, and IPFS. Handles encryption, peer discovery, real-time sync, and persistent snapshots so you can focus on your editor.
Documents are identified by an IPNS name (a self-certifying identifier) in the URL path; access level is encoded in the URL fragment as key material. Sharing a URL shares a capability. No accounts, no servers, no sign-up.
import { pokapali } from "@pokapali/core";
const app = pokapali({
appId: "my-app",
channels: ["content"],
origin: window.location.origin,
});
// Create a document (you become admin)
const doc = await app.create();
// Edit via Yjs
const ytext = doc.channel("content").getText("body");
ytext.insert(0, "Hello, world!");
// Share — the URL encodes the access level
console.log(doc.urls.write); // writer invite
console.log(doc.urls.read); // read-only link
// Open from a capability URL
const doc2 = await app.open(someUrl);| Package | Description |
|---|---|
@pokapali/core |
Document lifecycle, snapshot push/pull, capability URLs |
@pokapali/sync |
WebRTC room setup via GossipSub signaling |
@pokapali/crypto |
Key derivation (HKDF), Ed25519 signing, AES-GCM encryption |
@pokapali/capability |
Capability URL encoding/decoding and access level inference |
@pokapali/subdocs |
Yjs subdocument manager with channel isolation |
@pokapali/blocks |
Snapshot encoding, decoding, verification, and chain walking |
@pokapali/node |
Relay server, pinner, and HTTP block/health endpoints (Node.js) |
@pokapali/log |
Zero-dependency structured logging |
@pokapali/comments |
Comment threads with anchored text ranges |
@pokapali/comments-tiptap |
Tiptap extension for comment highlighting and pending anchors |
@pokapali/react |
React hooks for Doc state, participants, and comments |
@pokapali/test-utils |
Test helpers and simulated network |
Most apps only import @pokapali/core. The other
packages are the building blocks it composes.
- Getting Started — quick start with runnable examples
- Guide — build an app with Pokapali
- Integration Guide — add pokapali to an existing editor
- API Stability — which APIs are safe to depend on (Stable / Experimental / Internal tiers)
- Security Model — capability URLs, encryption, trust model, identity, and document recovery
- Troubleshooting — common errors and how to fix them
- Internals — architecture, design principles, security design, and dependency decisions (for contributors)
# Install dependencies
npm install
# Build all packages
npx tsc --build
# Run tests
npm test
# Run the example app (Vite dev server)
npm run dev
# Run a local relay + pinner node
npm run dev:nodeMonorepo managed with npm workspaces. TypeScript throughout, targeting ES2022/ESNext.
The example app is a collaborative text editor built with React and Tiptap. It demonstrates document creation, sharing via capability URLs, real-time sync, read-only access, threaded comments, version history, and connection diagnostics.
npm run devOpens at http://localhost:3141. Create a document, copy
the share URL, open it in another tab — edits sync in
real-time via WebRTC and persist via IPFS snapshots.
Capability URLs — the URL is the permission token. The path contains the public IPNS name; the fragment (never sent to servers) contains encrypted key material. Which keys are present determines access level (admin, writer, read-only).
Channel isolation — each channel (e.g. "content", "comments") is a separate Yjs subdocument synced over its own encrypted WebRTC room. Write enforcement is structural: no key = no room = no connection.
Snapshot persistence — full document state is periodically saved as a signed, encrypted IPFS block linked into an append-only chain. Any single snapshot is sufficient to recover the entire document.
GossipSub signaling — WebRTC connections are brokered via GossipSub (a peer-to-peer pub/sub protocol) over the libp2p mesh. No external signaling servers required.
Zero-knowledge pinners — relay/pinner nodes store and serve encrypted blocks they cannot read (they persist data without knowing its content). Anyone can run one.
See Internals for the full design.