Skip to content

Local-first apps that scale to the cloud with nothing to run

coven

Bring your own storage

Google DriveDropboxOneDriveiCloud (CloudKit)S3-compatible

Learn more →

How it works

The life of a store

Local first

The phone inserts a row. It commits on-device; nothing waits on a network.

rust
handle.sql(|sql| {
    sql.execute("INSERT …", params)?;
    Ok(())
}).await?;
PHONECLOUDLAPTOPnote · “milk run”(no cloud configured)(nothing yet)

Serverless sync

The cloud becomes the sync medium. Devices push sealed, signed objects and pull each other's; it only ever holds ciphertext.

rust
handle.connect_sync(Some(key)).await?;
PHONECLOUDLAPTOPnote · “milk run”push · sealedsigned objectpullnote · “milk run”

Everyone writes

Apart, both devices edit the same row. The next sync applies both: merge is column by column.

sql
UPDATE notes SET body = 'oat, 2%'
PHONECLOUDLAPTOPtitle → “Milk run”body → “oat, 2%”Δ title — phoneΔ body — laptopmerge on pullMilk runoat milk, 2%Milk runoat milk, 2%

Blobs, too

A photo commits in the row's transaction. The laptop takes the row now and streams the photo on first view.

rust
handle.write(
    |b| { b.put_blob(ns, id, bytes); Ok(()) },
    |sql| { /* INSERT the row */ Ok(()) },
).await?;
PHONECLOUDLAPTOPphotos rowIMG_204.jpgone transactionrow objectblob objectphotos rowIMG_204.jpgstreams on first view

Beyond the disk

The original moves to the cloud. Devices keep cache copies; a pin keeps one offline.

rust
handle.make_remote("photos", id, false).await?;
PHONECLOUDLAPTOPRAW original · 48 MBoffloadblob · 48 MBcache · streams on readcache copypinned copy

Pick what syncs

One flag shares a subtree. Flipping it on cascades the project's rows and files to peers; flipping it off retracts them from peers and keeps them local.

sql
UPDATE projects SET shared = 1
PHONECLOUDLAPTOPZine — shared ✓task rowphoto + fileΔ ZineΔ taskΔ photo + blobZinetask rowphoto + filelater, shared flips offZine — shared ✗task rowphoto + filedeletes emittedretracted

Released under the Apache-2.0 License.