Apps that just work.
Inspired by Linear’s sync engine. Open-source.
npx skills add stratasync/stratasyncMost apps don’t just work
Strata Sync changes that
No more spinners
Your data lives on the device, ready the moment you open the app.
Works offline
Edits apply immediately and sync to the server when you reconnect.
Always in sync
Real-time updates across every device and tab. No refresh banners, no stale data.
How Strata Sync compares
Strata Sync
ElectricSQL
Local storage
Built-in (IndexedDB)
Bring your own
Conflict resolution
Automatic, field-level
Bring your own
Real-time editing
Rich-text with Yjs
Not included
Offline writes
Full offline support
Bring your own
Undo and redo
Built-in
Not included
Strata Sync
ElectricSQL
Local storage
Built-in (IndexedDB)
Bring your own
Conflict resolution
Automatic, field-level
Bring your own
Real-time editing
Rich-text with Yjs
Not included
Offline writes
Full offline support
Bring your own
Undo and redo
Built-in
Not included
What you can build
Tick off items and reorder lists instantly, even in aeroplane mode.
Device A
Offline
Device B
Offline
Get started in minutes
npx skills add stratasync/stratasync1. Define your models · lib/sync/models.ts
import { ClientModel, Model, Property } from "@stratasync/core"
@ClientModel("Todo", { loadStrategy: "instant" })
class Todo extends Model {
@Property() declare title: string
@Property() declare completed: boolean
}2. Create the client · lib/sync/client.ts
import { createSyncClient } from "@stratasync/client"
import { createMobXReactivity } from "@stratasync/mobx"
import { createIndexedDbStorage } from "@stratasync/storage-idb"
import { GraphQLTransportAdapter } from "@stratasync/transport-graphql"
const client = createSyncClient({
storage: createIndexedDbStorage(),
transport: new GraphQLTransportAdapter({
endpoint: "/api/graphql",
syncEndpoint: "/api/sync",
wsEndpoint: "wss://api.example.com/sync/ws",
auth: { getAccessToken: async () => "token" },
}),
reactivity: createMobXReactivity(),
})3. Build reactive components · components/todo-list.tsx
import { observer } from "mobx-react-lite"
import { useQuery, useSyncClient } from "@stratasync/react"
const TodoList = observer(() => {
const { data: todos } = useQuery("Todo", {
where: (t) => !t.completed,
})
const { client } = useSyncClient()
const addTodo = async () => {
const todo = await client.create("Todo", {
title: "New todo",
completed: false,
})
todo.title = "Actually, a better title"
await todo.save()
}
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
<button onClick={addTodo}>Add</button>
</ul>
)
})