Zero-knowledge server
Room keys live only in the browser. The server sees hashed identifiers and opaque ciphertext — never plaintext data or encryption keys.
See the architectureSelf-hosted in one Docker command.
Add Google Docs-style multi-user editing, presence, and chat to any web app — where your server mathematically cannot read plaintext. Built on WebRTC, Yjs, and AES-256-GCM via the browser's native Web Crypto API.
MIT client · Apache 2.0 server · Self-hosted in one Docker command
Zero-knowledge by architecture, not by promise.
Room keys live only in the browser. The server sees hashed identifiers and opaque ciphertext — never plaintext data or encryption keys.
See the architectureHIPAA technical safeguards, attorney-client privilege, GDPR data-minimization by design. Not certified — architecture enables your own compliance program.
Run on your own Hetzner / AWS / bare metal via one Docker image. No vendor-cloud dependency. Server is Apache 2.0 — fully open-source, no license fees for self-hosting.
MIT-licensed client SDK. Web Crypto API only — no third-party crypto libraries. Property-based tests via fast-check. SLSA provenance on every release.
Companion package @tovsa7/zerosync-react — useYText, usePresence, useMyPresence, useConnectionStatus. Works with Tiptap, CodeMirror, Quill via standard Yjs bindings.
Products where two or more humans collaborate on sensitive content — and "your server cannot read it" is itself a feature.
Privileged attorney-client work, live document redlines, e-signing ceremonies with witnesses.
Attorney-client privilegeLike Notion for law firms — privilege guaranteed by architecture, not policy.
Therapist-client sessions with notes, homework, and chat that the platform itself cannot see.
HIPAA §164.312Like SimplePractice, but the vendor cannot read a single session.
Token deal rooms, M&A data rooms, OTC trading desk coordination, private equity deal flow.
Data-room gradeLike a VDR, but self-hosted and zero-knowledge end to end.
Cross-team collaboration on IP, patents, regulatory filings, and trade secrets.
Trade-secret protectionLike Confluence, but for material that must not leave your premises.
A DPA-grade architecture you can point at during procurement and security reviews.
GDPR Art. 28 / 32Like Liveblocks, but EU procurement-ready out of the box.
Spin up your own signaling server, then integrate the SDK. 30 lines total.
docker run -p 8080:8080 ghcr.io/tovsa7/zerosync-server:latest Production setup (TLS via Caddy, license, Docker Compose): SELF-HOSTED.md
npm install @tovsa7/zerosync-react @tovsa7/zerosync-client react yjs import { ZeroSyncProvider, useYText, useConnectionStatus } from '@tovsa7/zerosync-react'
import { deriveRoomKey } from '@tovsa7/zerosync-client'
function App({ roomKey }: { roomKey: CryptoKey }) {
return (
<ZeroSyncProvider
serverUrl="wss://sync.example.com/ws"
roomId="my-room"
roomKey={roomKey}
peerId={crypto.randomUUID()}
nonce={btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(16))))}
hmac=""
iceServers={[{ urls: 'stun:stun.l.google.com:19302' }]}
>
<Editor />
</ZeroSyncProvider>
)
}
function Editor() {
const status = useConnectionStatus()
const text = useYText('editor')
if (status !== 'connected') return <p>Status: {status}</p>
return (
<textarea
value={text?.toString() ?? ''}
onChange={(e) => {
text?.delete(0, text.length)
text?.insert(0, e.target.value)
}}
/>
)
} npm install @tovsa7/zerosync-client yjs import { Room, deriveRoomKey } from '@tovsa7/zerosync-client'
// Room key is derived client-side and never transmitted.
const secret = crypto.getRandomValues(new Uint8Array(32))
const roomKey = await deriveRoomKey(secret, 'my-room-id')
const room = await Room.join({
serverUrl: 'wss://your-server/ws',
roomId: 'my-room-id',
roomKey,
peerId: crypto.randomUUID(),
nonce: btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(16)))),
hmac: '',
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
})
const text = room.getDoc().getText('editor')
text.observe(() => console.log(text.toString()))
room.updatePresence({ name: 'Alice' })
room.leave() See the React hooks package for useYMap, useYArray, usePresence, and Tiptap / CodeMirror integration examples.
AES-256-GCM encryption applied client-side before any data leaves the browser.
Illustrative: your users read their content; the server handles only signaling metadata. Don't trust the picture — verify the architecture yourself below.
# Sprint Planning — Q2
- Launch target: May 15
- Design partners: 100
- Pricing model: per-bracket
- Risk: WebRTC NAT traversal
- Next review: Friday peer_id: sha256(9c2d7e84…)
room_id: sha256(4a8b3f91…)
ice: udp 192.0.2.5:54321
sdp: m=application DTLS
event: peers.connected
session: 1745420100 Signaling server source is Apache 2.0 — fully open-source, auditable, fork-friendly. Third-party security audit on the roadmap.
Full threat model + disclosure process: SECURITY.md
Versus the most common alternatives for real-time collaboration.
| ZeroSync | Liveblocks | Yjs + y-websocket | Jazz.tools | |
|---|---|---|---|---|
| End-to-end encrypted | AES-256-GCM | | | opt-in |
| Zero-knowledge server | | | | |
| Self-hosted | | cloud only | | |
| Open-source | MIT + Apache 2.0 | | MIT | MPL-2.0 |
| React hooks | | | community | |
Questions I get from security-conscious CTOs during evaluation.
Didn't find your question? Email me directly.
I'm onboarding a small group of design partners — companies shipping HIPAA / GDPR / privilege-sensitive collaboration. In exchange for deep feedback, you get direct influence on the product and pricing that stays friendly as you grow.
Email goes straight to me — no support tiers, no tickets. You talk to the person who writes the code.
Your use case shapes the next quarter. Needed features jump the queue — you see what ships because of you.
Today's rate stays locked in as standard prices rise. No surprise hikes when you scale your deployment.
Pair-programming for self-hosted setup. TOM compliance template. We debug your NAT or WebRTC issues together.
contact.zerosync@proton.me