Skip to content

Repository files navigation

A local-first sync engine for TypeScript, React, and Next.js, built on the architecture Linear never open-sourced

Every read is instant, every write works offline, and every client converges.

Docs

Models, adapters, and the sync protocol, with a full API reference.

Read the docs

Install

npm install @stratasync/core @stratasync/client @stratasync/react @stratasync/mobx @stratasync/storage-idb @stratasync/transport-graphql

Quickstart

Three files. Or run npx skills add mblode/stratasync and let the skill scaffold them for you.

1. 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 = () =>
    client.create("Todo", { title: "New todo", completed: false });

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
      <button onClick={addTodo}>Add</button>
    </ul>
  );
});

What you get

  • Instant reads: every query hits a local IndexedDB replica, so there are no spinners and no round-trips.
  • Writes that survive offline: they queue locally and sync when the connection returns.
  • Fine-grained reactivity: MobX observables mean only the components touching changed data re-render.
  • Live collaboration and undo: Yjs CRDTs let several people edit one document, with history tracked per transaction.
  • Swappable adapters: storage, transport, and reactivity are each a separate package.

Packages

Ten packages, so you install only the layers you use. Runnable examples live in examples/web and examples/api.

core Models, properties, and the sync protocol
client The sync client and its lifecycle
react useQuery, useSyncClient, and the provider
next Next.js App Router integration
mobx MobX reactivity adapter
y-doc Yjs CRDT documents for collaborative fields
server The sync server and delta packet endpoints
storage-idb IndexedDB replica for the browser
storage-local In-memory replica for tests and SSR
transport-graphql GraphQL transport over HTTP and WebSocket

License

MIT


Crafted by Matthew Blode

About

Sync that works offline.

Topics

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages