Skip to content

πŸ”„ A powerful, type-safe sync engine for building real-time collaborative applications. Local-first, CRDT-based, with zero-config offline support.

License

Notifications You must be signed in to change notification settings

Dancode-188/synckit

SyncKit

True offline-first sync for modern appsβ€”without vendor lock-in

npm version Build Status License Bundle Size TypeScript PRs Welcome

Getting Started β€’ Documentation β€’ Examples β€’ Discussions β€’ Roadmap


🎯 What is SyncKit?

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 conflicts

🎬 See It In Action

1. Complex State (Kanban) SyncKit handles structural data like lists and nested objects with automatic conflict resolution.

SyncKit Kanban Demo

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)


✨ Why SyncKit?

πŸš€ Works When Internet Doesn't

True offline-first architectureβ€”not just caching. Your app works perfectly on planes, trains, tunnels, and coffee shops with spotty WiFi.

πŸ“¦ Production-Ready, Feature-Complete

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.

πŸ”“ Your Data, Your Rules

Open source and self-hostable. No vendor lock-in, no surprise $2,000/month bills, complete data sovereignty.

⚑ Fast by Design

  • <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)

πŸ›‘οΈ Data Integrity Guaranteed

  • 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)

πŸš€ Quick Start

Installation

npm install @synckit-js/sdk

Your First Synced App

import { 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)

Full tutorial (5 minutes) β†’


πŸŽ“ Features

Text Editing & Collaboration

  • ✍️ 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)

Framework Integration

  • βš›οΈ 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

Core Capabilities

  • πŸ”„ 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

πŸ—οΈ Architecture

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
Loading

Detailed architecture docs β†’


πŸ“š Documentation

Getting Started

Core Concepts

Migration Guides

Examples

Browse all docs β†’


🎯 Use Cases

Tier 1: Simple Object Sync (LWW)

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-Wins

Tier 2: Collaborative Text Editing

Perfect 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 convergence

Tier 3: Counters & Sets

Perfect 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 set

🌐 How SyncKit Fits the Ecosystem

Different 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 ⚠️ Limited βœ… Yes
Undo/Redo βœ… Cross-tab ❌ No ❌ No ⚠️ Basic βœ… Yes
Awareness/Cursors βœ… Built-in ❌ No ❌ No ⚠️ Extension ❌ No
Framework Adapters βœ… React/Vue/Svelte ❌ No ❌ No ⚠️ Community ❌ No
True Offline-First βœ… Native ⚠️ Limited (cache + persistence) ❌ 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 ⚠️ Issues βœ… Good
Production Status βœ… v0.2.0 βœ… Mature βœ… Mature βœ… Mature ⚠️ Stable core,
evolving ecosystem

When to Choose SyncKit

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 β†’


πŸ“¦ Packages

Core

  • @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)

Servers

  • @synckit-js/server - Bun + Hono reference server (production-ready)

🚦 Status

Current Version: v0.2.0

Production Ready βœ…

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

Public Beta πŸ”Ά

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

What's Next 🚧

  • 🚧 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)

Full roadmap β†’


🀝 Contributing

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

Contributing guide β†’


🏒 Enterprise

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]


πŸ“Š Benchmarks

Bundle Size (gzipped)

SyncKit (lite):      46 KB β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
Yjs (assembled):     65 KB β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
SyncKit (default):  154 KB β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
Firebase:           150 KB β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
Automerge:          300 KB β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ

Sync Performance

Local update:       <1 ms  β–ˆβ–ˆβ–ˆβ–ˆ
Cross-tab sync:     <1 ms  β–ˆβ–ˆβ–ˆβ–ˆ
Network sync:    10-50 ms  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
Firebase (cold):  2-30 s   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ

Memory Usage (10K documents)

SyncKit:       3 MB  β–ˆβ–ˆβ–ˆβ–ˆ
Yjs:           8 MB  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
Automerge:   180 MB  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ

Detailed benchmarks β†’


πŸ™ Acknowledgments

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.


πŸ“„ License

MIT License - see LICENSE for details.

Copyright (c) 2025 Daniel Bitengo


πŸ”— Links


Built with ❀️ for the local-first future

⭐ Star us on GitHub β€’ πŸ“– Read the docs β€’ πŸš€ Get started

About

πŸ”„ A powerful, type-safe sync engine for building real-time collaborative applications. Local-first, CRDT-based, with zero-config offline support.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •