# SyncKit wraps CRDT collaboration into a three line document API

> SyncKit is a local-first sync engine for React, Vue and Svelte that ships rich text, undo/redo, presence and cursor sharing, backed by Fugue and Peritext CRDTs and a multi-language implementation. The API is small, the bundle is 154KB, and the project is still on version 0.3.0.

**Dancode-188/synckit** —  Local-first collaboration SDK for React, Vue, and Svelte. Batteries-included: Rich text, undo/redo, cursors, and presence.

- Repository: https://github.com/Dancode-188/synckit
- Stars: 669 · Forks: 22
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/dancode-188-synckit

## The public surface is a document object with an update method

SyncKit is described as a sync engine for local-first collaboration, and the entry point is deliberately small. You construct the engine, initialise it, ask for a document by identifier and update it.

```typescript
const sync = new SyncKit()
await sync.init()
const doc = sync.document<Todo>('todo-123')
await doc.update({ completed: true })
```

The package is published to npm under the name @synckit-js/sdk and installs like any other dependency.

```bash
npm install @synckit-js/sdk
```

The point of that shape is that a document is addressed by a string, updates are plain object writes, and the engine takes care of persistence, transport and merging. Initialisation is described as working offline only with no server needed, and the local storage layer is IndexedDB. The tradeoff is that the document API is generic: it does not know whether it holds a todo list, a paragraph of rich text or a counter, so the specialised behaviour comes from the data types and the feature modules rather than from the document object itself.

## Text merges through Fugue and Peritext while plain fields use last write wins

The conflict semantics are the part to read carefully, because they are not uniform. Concurrent text edits merge through the Fugue CRDT for plain text and the Peritext CRDT for rich text formatting, which is what makes bold, italic and links survive simultaneous edits. Concurrent writes to the same document field resolve by last write wins, so one write is chosen rather than both being kept. That is a defensible design, and it is also a place where surprises live: a plain counter or a status field in your model will not merge intelligently, it will simply take the later value. The feature list adds distributed data structures for counters and sets, with a PN-Counter and an OR-Set, and the demo application demonstrates the OR-Set through a community voting feature it calls the Word Wall. Undo and redo are part of the same story, described as cross-tab undo that syncs everywhere and persists across sessions, which is a harder problem than a local undo stack and a reason to test it before trusting it.

## Presence, cursor sharing and framework adapters round out the package

Beyond the CRDT core, the project lists awareness and presence, so you can see who is online and what they are editing, and cursor sharing with real time cursor positions. Those features are the ones that make a collaborative editor feel alive, and they are also the ones that cost the most to build and to test. The framework integration is provided as three separate adapter styles: React hooks as a complete hook library, Vue composables for the Vue 3 Composition API, and Svelte stores for Svelte 5 with runes support. A React consumer therefore imports the hook rather than reaching into the engine, and a Vue or Svelte consumer does the same with their own idiom.

```typescript
import { SyncKit } from '@synckit-js/sdk'
import { useSyncDocument } from '@synckit-js/sdk/react'
const sync = new SyncKit()
await sync.init()
const [tasks, { update }] = useSyncDocument<Task[]>('tasks')
```

The repository also carries an examples directory, a demo directory with its own Dockerfile, a Vite configuration and a fly.toml, and a docs directory with a getting started guide, so the intended path is to read a guide and then adapt one of the examples.

## Bundle size is the trade the lite variant exists to solve

Size is treated as a first class design constraint here, and the numbers are published in the project documentation. The full package is 154KB gzipped, and the documentation puts the complete figure with React at roughly 310KB, describing that as comparable to React alone. A lite variant is offered at 46KB gzipped for size critical applications, and it is imported as @synckit-js/sdk/lite with basic sync only. The project is explicit that the choice is completeness over minimal size, since rich text, undo and redo, cursors and the framework adapters all work together out of the box. That framing tells you what a reviewer should check. If your application is a data grid where the collaborative surface is a handful of fields, the lite build is probably enough, and the difference between 46KB and 154KB decides the framework choice downstream. If it is a document editor, the full build is the only thing that gives you the features, and the 154KB figure should be weighed against what else is in the bundle rather than in isolation.

## The implementation is a monorepo spanning TypeScript, Rust and a server

The package manifest shows the shape of the project, and it is broader than a single npm package. The root is a private workspace named synckit-monorepo whose version matches the newest release, with workspaces for the sdk and for the examples. The test script is the clearest window into the implementation, because it runs the SDK tests, then the server tests with bun, then the core tests with cargo, meaning the core is a Rust library built and tested through Cargo while the server has a TypeScript implementation. The topics attached to the repository list crdt, distributed-systems, local-first, wasm, rust and sdk, which fits a Rust core compiled to WebAssembly for the browser and running natively elsewhere. The tree also has a protocol directory, a core directory, a server directory, a benchmarks directory and a stress-test directory, plus a fetch_pr.sh script and a scripts directory. The project states that it is formally modelled with TLA+ and that the specifications are in the repository, and it claims more than 2,100 tests across TypeScript, Rust, Python, Go and C#, covering unit, integration, chaos and load cases.

## Self hosting is the stated alternative to a hosted sync service

The positioning is explicitly anti vendor lock-in. The project presents itself as open source and self hostable, with data sovereignty as a feature rather than a compliance footnote, and the server directory in the repository is the counterpart to that claim. For a team that has to run its own synchronization backend, that is the part that matters, and the demo directory shows what a deployment looks like in practice, with a Dockerfile, an nginx configuration file, a fly.toml and a Vite build, all for a single demo application. The local write demo is the quickest way to see the behaviour, and the project describes a thirty second test that opens the demo in two browser tabs, joins the same room in both, types in one and watches the text appear in the other with live cursors. The offline behaviour is described in the same terms, disconnecting the network, continuing to edit and letting the changes sync on reconnect. What the project does not supply is a hosted service with an availability commitment, so the operational burden of running the servers falls on whoever adopts it.

## Version 0.3.0 is the current shape of a fast moving API

Maintenance facts for SyncKit are about velocity. The release list shows v0.2.0 and v0.2.2 in December 2025, both described as the complete local first collaboration platform, and v0.3.0 in February 2026 described as production ready multi-language servers. The last push was on 2026-10-18, the repository is not archived, and the package version in the manifest matches the newest release. A pre 1.0 version number is the honest signal here: the feature set is broad, the documentation is thorough, and the API is still moving. There is a ROADMAP.md, a SECURITY.md, a CONTRIBUTING.md, a CODE_OF_CONDUCT.md and an AUTHORS.md in the tree, which is the administrative scaffolding of a project that expects outside contributions, and the badge in the README points at a getting started guide, documentation index, examples, discussions and the roadmap. The licence is MIT. For an adopting team the sensible posture is to pin an exact version, read the roadmap for what is about to change, and treat the documented performance figures, sub millisecond local operations and sync latency in the tens of milliseconds, as claims from the project rather than as measurements you have made.

## Conclusion

SyncKit is a reasonable starting point for a team that has decided to build a collaborative editor in the browser and would rather not assemble CRDTs, presence and undo/redo themselves, particularly if the app already stores state in IndexedDB and can run without a server. It is the wrong choice for a team that needs a stable public API, because the newest release is v0.3.0 and the project is still changing shape, and the wrong choice for anyone who cannot accept a WebAssembly core in the browser, since the implementation spans TypeScript and Rust. Verify three things before committing: that the conflict semantics match your model, which means reading the last write wins rule for document fields against the Fugue and Peritext merging for text, that the 154KB payload is acceptable against the 46KB lite variant, and that the servers you run for multi device sync are the ones in the server directory rather than a third party. The licence is MIT, the last push was on 2026-10-18, and there is a published roadmap and a security policy in the repository.

## FAQ

### How do I install SyncKit and create a synced document?

Install the package with npm install @synckit-js/sdk, then construct SyncKit, await sync.init(), and request a document by identifier with sync.document. Updates are applied with the document's update method. The project states that initialisation works offline with no server needed.

### How does SyncKit resolve conflicting edits?

Concurrent text edits merge through the Fugue CRDT for plain text and Peritext for rich text formatting, while concurrent writes to the same document field resolve by last write wins so one write is chosen. Distributed counters and sets are provided as a PN-Counter and an OR-Set.

### What is the difference between the full SDK and the lite build?

The full package is 154KB gzipped and includes rich text, undo and redo, presence, cursor sharing and the framework adapters, while the lite variant is 46KB gzipped with basic sync only and is imported from @synckit-js/sdk/lite.

### Which frameworks does SyncKit support?

Three adapters are provided: React hooks as a complete hook library, Vue composables for the Vue 3 Composition API, and Svelte stores for Svelte 5 with runes support. The repository also ships examples and a demo application built with Vite and Docker.

## Sources

- [Dancode-188/synckit on GitHub](https://github.com/Dancode-188/synckit)
- [Issues](https://github.com/Dancode-188/synckit/issues)
- [License: MIT](https://github.com/Dancode-188/synckit/blob/main/LICENSE)
- [README](https://github.com/Dancode-188/synckit/blob/main/README.md)
- [Releases](https://github.com/Dancode-188/synckit/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dancode-188-synckit
