Looks interesting, was looking for something like this as currently for Flutter I use Loro via flutter_rust_bridge as the CRDT data store, but it's not SQL so some things like big queries are annoying. How are you handling CRDTs in a SQL database? I thought those were notoriously hard as relational wasn't built for CRDT style syncing?
I wish there was an established way to build local first software with a robust syncing in the background, either P2P or to a server.
I feel projects like this for local first and projects like Iroh for connectivity over NAT and through firewalls need to come together more.
It would be could to have a drop in framework for this.
This is cool. Reminds of Lotus Notes. In a strange way a concept that felt "outdated" is something that I would love to be the default behavior for many apps today.
It’s a bit weird to see every comment here talks about apps she or he has built but never really give a shit about this app itself.
In which way this is different from PowerSync?
Interesting! I wrote something similar for my app recently, it was the first thing I coded using LLMs.
Be warned, AI Slop ahead
Hi HN! I’ve been circling this problem for a long time.
In 2019 I built an offline-first datastore called debe. It used CRDTs and multi-master replication and never became something I could confidently ship. It did teach me that convergence is only a small part of sync. The difficult parts are durable writes, authorization changes, lost acknowledgements, schema upgrades, bounded bootstrap, and explaining what happened after something fails.
I eventually came back to the problem and built Syncular over the last year.
Every client has a real SQLite database: sqlite-wasm on OPFS in the browser and native SQLite elsewhere. Writes apply locally and enter a durable outbox in the same transaction. A server-authoritative commit log validates and orders them, using explicit scopes resolved inside the application backend.
The protocol is written down independently of the implementations. SSP2 is currently a draft, with canonical binary encoding and golden byte vectors. There are independent TypeScript and Rust client cores, both run against the same 95-scenario conformance catalog. The Rust core is exposed through Swift, Kotlin, Flutter, React Native, Tauri, Rust, and a small C API.
It also includes realtime WebSocket sync, resumable bootstrap segments, explicit conflict evidence, authorization revocation and local purge, windowed replicas, blobs, optional CRDT columns, per-column encryption, and typesafe generated queries for five languages. Important boundaries: it is pre-1.0, self-hosted, and there is no managed service or peer-to-peer mode. Native packaging maturity still varies by ecosystem.
Let me know what you think, I'm happy about feedback!
Demo: https://demo.syncular.dev Protocol: https://github.com/syncular/syncular/blob/main/docs/SPEC.md Background: https://syncular.dev/blog/offline-first-writes/ Docs: https://syncular.dev/
No mention of conflict resolution? I suspect it's far too naive to be useful for anything real.