Skip to content

Repository files navigation

Animated syncular ASCII singularity

syncular

Syncular keeps an SQLite database on each client and synchronizes it through a server-owned commit log. Apps read from local SQLite and continue to work offline. A write updates local state immediately, enters an outbox, and is checked by the server when it syncs.

The browser client runs SQLite on OPFS. Native integrations share the Rust core and native SQLite across Rust, Swift, Kotlin, Flutter, React Native, and Tauri. Servers run on Bun, Node, or Cloudflare Workers with SQLite, Postgres, or D1. Backend services and workers can run a server-side SyncClient with persistent SQLite (often called a headless client). A database-less SyncRemoteClient submits commits and calls registered server operations. Applications can store domain actions as event rows alongside their related writes.

Documentation · Quickstart · Live demos · Benchmarks · Blog

Try it

bun create syncular-app my-app --template minimal

The minimal template creates a server, a schema, two independent clients, and a smoke test. The five-minute quickstart walks through the generated project and runs the two clients against each other.

Project status

Syncular is pre-1.0 and currently maintained by me, Benjamin Kniffler. The wire protocol is written down and checked across two implementations. Public APIs and protocol details can still change before 1.0. Changes are recorded in docs/RELEASE.md.

How behavior is checked

docs/SPEC.md defines the sync wire protocol, docs/REMOTE.md defines registered remote operations, and spec/vectors/ contains its byte-level fixtures. The TypeScript and Rust cores run the same implementation-independent conformance catalog. A behavior change that affects both cores has to update the spec and add a conformance scenario.

Integration tests use an in-memory transport with deterministic fault injection. They wait for explicit readiness signals; sleeps are banned. A small set of adapter tests exercises real sockets. The details live in packages/conformance.

Repository map

Path What it contains
packages/core Protocol codecs, shared types, vector round-trips
packages/server Server protocol handler plus storage and authorization interfaces
packages/server-hono, packages/server-workers Hono and Cloudflare Workers bindings
packages/web-client @syncular/client, the TypeScript client core on SQLite
packages/react React hooks over the client
packages/typegen Schema and query compiler with TypeScript, Swift, Kotlin, Dart, and Rust output
packages/crypto, packages/crdt-yjs Column encryption and Yjs CRDT integration
packages/testing @syncular/testkit, an in-process server and clients
packages/conformance The scenario catalog both cores run
rust/ Rust client core, command surface, and C FFI
bindings/ Tauri, React Native, Swift, Kotlin, and Flutter bindings
apps/docs The syncular.dev source

Development

bun install
bun run check   # typecheck + lint + test

Read AGENTS.md before contributing. It contains the rules that apply to maintainer work and external contributions.

LLMs

This README has had plenty of LLM help. So has the rest of the project: docs, tests, benchmarks, production code. Syncular itself wasn't prompted into existence though; I've spent years on offline-first problems, built debe back in 2019, and studied PowerSync, Zero, Electric, Replicache, Turso, LiveStore, and Jazz closely before writing this engine. The concepts and their first implementations are hand-written, and the checks above apply to every diff no matter where it came from. The full story is at syncular.dev/llms.

Contributions with LLM help are welcome. If a model drafted or rewrote something that's still in your pull request, say so in the description. Read your own diff and be ready to explain it; pull requests pasted straight out of a model are closed without comment.

About

Offline-first SQL sync with Typescript and Rust cores

Topics

Resources

Stars

247 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages