True offline-first sync for modern appsβwithout vendor lock-in
Getting Started β’ Documentation β’ Examples β’ Discussions β’ Roadmap
Build collaborative apps in hours, not months.
SyncKit is a production-ready sync engine that gives you everything for local-first collaboration:
- Rich text editing with conflict resolution (Peritext + Fugue CRDTs)
- Undo/redo that syncs across tabs and sessions
- Live presence and cursor sharing
- Framework adapters for React, Vue, and Svelte
"Add
sync.document()to your app, get real-time sync automatically."
The reality: Building sync from scratch takes months. SyncKit gives you production-ready collaboration in 3 lines of code.
const sync = new SyncKit()
await sync.init()
const doc = sync.document<Todo>('todo-123')
await doc.update({ completed: true })
// β¨ Works offline, syncs automatically, resolves conflicts1. Complex State (Kanban) SyncKit handles structural data like lists and nested objects with automatic conflict resolution.
2. Collaborative Text (New in v0.2.0) Add Google Docs-style collaboration to your app with a single hook.
// It's this simple:
import { useSyncText } from '@synckit-js/sdk/react'
function Editor() {
// β¨ Automatic conflict resolution & real-time sync
const [text, { insert, delete: del }] = useSyncText('doc-1')
return <textarea value={text} onChange={e => insert(0, e.target.value)} />
}(Live text editing demo coming soon)
True offline-first architectureβnot just caching. Your app works perfectly on planes, trains, tunnels, and coffee shops with spotty WiFi.
154KB gzipped - Complete local-first sync solution with everything you need.
What you get:
- β Text editing (Fugue CRDT) - Collaborative editing that just works
- β Rich text formatting (Peritext) - Bold, italic, links with conflict resolution
- β Undo/redo - Syncs across tabs, persists across sessions
- β Real-time presence - See who's online, what they're editing
- β Cursor sharing - Watch teammates type in real-time
- β Counters & Sets - Distributed data structures for app state
- β Framework adapters - React, Vue, Svelte (choose what you need)
- β Offline-first sync - Works perfectly without internet
- β IndexedDB persistence - Unlimited local storage
Size-critical apps? Use Lite variant (46KB gzipped, basic sync only)
Every byte is justified. We chose completeness over minimal sizeβrich text, undo/redo, cursors, and framework adapters all work together out of the box.
Open source and self-hostable. No vendor lock-in, no surprise $2,000/month bills, complete data sovereignty.
- <1ms local operations (~5-20ΞΌs single field update)
- <100ms sync latency (10-50ms p95)
- 154KB bundle (complete solution), 46KB lite option
- ~310KB total with React (comparable to React alone)
- Zero data loss with automatic conflict resolution (Last-Write-Wins)
- Formal verification with TLA+ (3 bugs found and fixed)
- 1,081+ comprehensive tests across TypeScript and Rust (unit, integration, chaos, load)
npm install @synckit-js/sdkimport { SyncKit } from '@synckit-js/sdk'
import { SyncProvider, useSyncDocument } from '@synckit-js/sdk/react'
// Initialize (works offline-only, no server needed!)
const sync = new SyncKit()
await sync.init()
function App() {
return (
<SyncProvider synckit={sync}>
<TodoApp />
</SyncProvider>
)
}
function TodoApp() {
const [todo, { update }] = useSyncDocument<Todo>('todo-1')
if (!todo || !todo.text) return <div>Loading...</div>
return (
<div>
<input
type="checkbox"
checked={todo.completed}
onChange={(e) => update({ completed: e.target.checked })}
/>
<span>{todo.text}</span>
</div>
)
}That's it! Your app now:
- β Works 100% offline
- β Syncs across tabs automatically
- β Persists data in IndexedDB
- β Resolves conflicts automatically
Bundle: SyncKit (154KB gzipped) + React (156KB) = ~310KB total
Size-critical? import { SyncKit } from '@synckit-js/sdk/lite' (46KB gzipped, local-only)
- βοΈ Text CRDT (Fugue) - Collaborative editing with conflict-free convergence
- π¨ Rich Text (Peritext) - Bold, italic, links with proper formatting merge
- β©οΈ Undo/Redo - Cross-tab undo that syncs everywhere
- π₯ Awareness & Presence - See who's online and what they're editing
- π±οΈ Cursor Sharing - Real-time cursor positions with smooth animations
- π’ Counters & Sets - Distributed counters (PN-Counter) and sets (OR-Set)
- βοΈ React Hooks - Complete hook library for all features
- π’ Vue Composables - Idiomatic Vue 3 Composition API integration
- πΆ Svelte Stores - Reactive Svelte 5 stores with runes support
- π Real-Time Sync - WebSocket-based instant sync across devices
- π΄ Offline-First - Works perfectly with zero connectivity
- ποΈ Local Persistence - IndexedDB storage, unlimited capacity
- π Conflict Resolution - Automatic Last-Write-Wins (LWW) merge for documents, CRDTs for collaboration
- β‘ Fast Operations - <1ms local updates, <100ms sync latency
- π¦ Production Bundle - 154KB gzipped (complete) or 46KB (lite)
- π Secure - JWT authentication, RBAC permissions
graph TD
A[Your Application<br/>React/Vue/Svelte] --> B[SyncKit SDK<br/>TypeScript]
B -->|Simple API| B1[document, text, counter]
B -->|Framework adapters| B2[React/Vue/Svelte hooks]
B -->|Offline queue| B3[Storage adapters]
B --> C[Rust Core Engine<br/>WASM + Native]
C -->|80% of use cases| C1[LWW Sync]
C -->|Collaborative editing| C2[Text CRDTs]
C -->|Advanced features| C3[Custom CRDTs<br/>counters, sets]
C --> D[IndexedDB Storage<br/>Your local source of truth]
D -.->|Optional| E[SyncKit Server<br/>TypeScript/Python/Go/Rust]
E -->|Real-time sync| E1[WebSocket]
E -->|Persistence| E2[PostgreSQL/MongoDB]
E -->|Security| E3[JWT auth + RBAC]
style A fill:#e1f5ff,stroke:#333,stroke-width:2px,color:#1a1a1a
style B fill:#fff4e1,stroke:#333,stroke-width:2px,color:#1a1a1a
style C fill:#ffe1e1,stroke:#333,stroke-width:2px,color:#1a1a1a
style D fill:#e1ffe1,stroke:#333,stroke-width:2px,color:#1a1a1a
style E fill:#f0e1ff,stroke:#333,stroke-width:2px,color:#1a1a1a
Detailed architecture docs β
- 5-Minute Quick Start - Build your first synced app
- Installation Guide - Setup instructions
- API Reference - Complete API documentation
- Offline-First Patterns - True offline architecture
- Conflict Resolution - Automatic LWW merge strategy
- Performance Optimization - Bundle size, memory, sync speed
- Testing Guide - Property-based tests, chaos engineering
- From Firebase/Firestore - Escape vendor lock-in
- From Supabase - Add offline support
- From Yjs/Automerge - Simplify your stack
- Vanilla Counter - Minimal example with no build tools (just open in browser!)
- Todo App - Simple CRUD with filters
- Collaborative Editor - Real-time text editing with CodeMirror 6
- Project Management - Production-grade kanban app with drag-and-drop
Perfect for: Task apps, CRMs, project management, note apps (80% of applications)
import { SyncKit } from '@synckit-js/sdk'
import { useSyncDocument } from '@synckit-js/sdk/react'
// Initialize once
const sync = new SyncKit()
await sync.init()
// Use anywhere
const doc = sync.document<Project>('project-123')
await doc.update({ status: 'completed' })
// Conflicts resolved automatically with Last-Write-WinsPerfect for: Collaborative editors, documentation, notes
import { useSyncText } from '@synckit-js/sdk/react'
const [text, { insert, delete: del }] = useSyncText('document-456')
await insert(0, 'Hello ')
// Character-level sync, conflict-free convergencePerfect for: Likes, votes, tags, participants
import { useCounter, useSet } from '@synckit-js/sdk/react'
const [count, { increment, decrement }] = useCounter('likes-789')
await increment() // Conflict-free counter
const [tags, { add, remove }] = useSet<string>('post-tags')
await add('typescript') // Observed-remove setDifferent libraries make different trade-offs. Here's how SyncKit compares:
| Feature | SyncKit | Firebase | Supabase | Yjs | Automerge |
|---|---|---|---|---|---|
| Bundle Size (gzipped) | 154KB (46KB lite) |
~150β200KB (typical client) |
~45KB (JS client) |
65KB (core) |
300KB+ (JS/WASM) |
| Text CRDT | β Fugue | β No | β No | β Y.Text | β Yes |
| Rich Text | β Peritext | β No | β No | β Yes | |
| Undo/Redo | β Cross-tab | β No | β No | β Yes | |
| Awareness/Cursors | β Built-in | β No | β No | β No | |
| Framework Adapters | β React/Vue/Svelte | β No | β No | β No | |
| True Offline-First | β Native | β No native support | β Full | β Full | |
| Works Without Server | β Yes | β No | β No | β Yes | β Yes |
| Self-Hosted | β Yes | β No | β Yes | β Yes | β Yes |
| TypeScript Support | β Native | β Good | β Good | β Good | |
| Production Status | β v0.2.0 | β Mature | β Mature | β Mature | evolving ecosystem |
Choose SyncKit if:
- β You need rich text, undo/redo, cursors, and framework adapters included
- β You want Vue or Svelte support (not just React)
- β You value shipping fast over optimizing every byte
- β You want true offline-first without vendor lock-in
Choose alternatives if:
- Firebase/Supabase: You need a full backend-as-a-service (auth, storage, functions) and offline sync isn't critical
- Yjs: Minimal bundle size is your #1 priority and you're okay wiring up separate plugins for undo, presence, and framework support.
- Automerge: You need JSON patching or unique Automerge features (and can accept 300KB+ bundle)
See detailed migration guides β
@synckit-js/sdk- Core SDK (TypeScript) + WASM engine@synckit-js/sdk/react- React hooks and components (export from SDK)@synckit-js/sdk/vue- Vue 3 composables (export from SDK)@synckit-js/sdk/svelte- Svelte 5 stores with runes (export from SDK)@synckit-js/sdk/lite- Lightweight version (local-only, 46KB gzipped)
@synckit-js/server- Bun + Hono reference server (production-ready)
Current Version: v0.2.0
The core sync engine is battle-tested and ready for production:
- β Document Sync - LWW conflict resolution with vector clocks
- β Text CRDT (Fugue) - Collaborative text editing with conflict-free convergence
- β Rich Text (Peritext) - Bold, italic, links with formatting conflict resolution
- β Counters & Sets - PN-Counter and OR-Set CRDTs
- β Offline-First Architecture - Works perfectly without internet
- β WebSocket Protocol - Real-time server synchronization
- β Core Rust Engine - Memory-safe WASM with zero unsafe blocks
- β WASM Compilation - 154KB gzipped (46KB lite), optimized performance
- β TypeScript SDK - Document, Text, RichText, Counter, Set APIs
- β Storage Adapters - IndexedDB and Memory storage
- β TypeScript Server - WebSocket sync server with Bun + Hono
- β 1,081+ Tests - 87% code coverage, 100% pass rate
- β Example Applications - Todo app, collaborative editor, project management
New features we're testing with the community - stable but gathering feedback:
- πΆ Undo/Redo - Cross-tab undo with persistent history
- πΆ Awareness & Presence - Real-time user tracking
- πΆ Cursor Sharing - Live cursor positions with animations
- πΆ Cross-Tab Sync - BroadcastChannel-based synchronization
- πΆ React Hooks - useSyncText, useRichText, usePresence, useOthers, useUndo
- πΆ Vue 3 Composables - Composition API integration
- πΆ Svelte 5 Stores - Reactive stores with runes support
- πΆ Quill Integration - QuillBinding for Quill editor
- π§ Multi-Language Servers - Python, Go, Rust implementations
- π§ Advanced Storage - OPFS (Origin Private File System), SQLite adapter
- π§ Conflict UI - Visual conflict resolution interface
- π§ Performance - Large document optimization (>10K chars)
We welcome contributions from the community!
Ways to contribute:
- π Bug Reports - Open an issue
- π Documentation - Improve guides, fix typos
- π§ͺ Tests - Add test coverage
- π Servers - Implement Python/Go/Rust servers
- π‘ Features - Propose new features in discussions
Need enterprise support?
- π― Managed Hosting - We host SyncKit servers for you
- π Priority Support - 24/7 support, SLA guarantees
- π Monitoring & Analytics - Dashboard, alerts, insights
- π Training & Consulting - Onboarding, architecture review
Contact: [email protected]
SyncKit (lite): 46 KB ββββββββ
Yjs (assembled): 65 KB βββββββββββ
SyncKit (default): 154 KB ββββββββββββββββββββββββββββ
Firebase: 150 KB ββββββββββββββββββββββββββββ
Automerge: 300 KB ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Local update: <1 ms ββββ
Cross-tab sync: <1 ms ββββ
Network sync: 10-50 ms ββββββββ
Firebase (cold): 2-30 s ββββββββββββββββββββββββββββββββ
SyncKit: 3 MB ββββ
Yjs: 8 MB βββββββββ
Automerge: 180 MB ββββββββββββββββββββββββββββββββββββββββ
Built with inspiration from:
- Yjs - Text CRDT concepts and performance optimization
- Automerge - CRDT theory and formal verification
- Linear - Pragmatic approach to sync
- Figma - Custom sync architecture patterns
- RxDB - Local-first database patterns
Special thanks to the local-first community for pioneering this movement.
MIT License - see LICENSE for details.
Copyright (c) 2025 Daniel Bitengo
- Documentation - Complete guides and API reference
- GitHub - Source code
- Issues - Bug reports and features
- Roadmap - Development timeline
- Discussions - Community discussions
- LinkedIn - Connect and follow updates
Built with β€οΈ for the local-first future
β Star us on GitHub β’ π Read the docs β’ π Get started