Skip to content

state-syncReliable state synchronization between windows/processes

Revision-based ordering â€Ē Multi-framework â€Ē Persistence & cross-tab sync

$ npm install @statesync/coreClick to copy
npm versionbundle sizelicensestars

Install ​

bash
npm install @statesync/core
bash
pnpm add @statesync/core
bash
yarn add @statesync/core
Optional packages
bash
# Persistence (caching, migrations, cross-tab sync)
npm install @statesync/persistence

# Framework adapter (pick one)
npm install @statesync/redux    # React + Redux / RTK
npm install @statesync/zustand  # React + Zustand
npm install @statesync/jotai    # React + Jotai
npm install @statesync/mobx     # MobX
npm install @statesync/pinia    # Vue + Pinia
npm install @statesync/valtio   # React + Valtio
npm install @statesync/svelte   # Svelte
npm install @statesync/vue      # Vue (reactive/ref)

# Transport adapter
npm install @statesync/tauri    # Tauri v2

Supported Frameworks ​

Do you need state-sync? ​

Yes, if you have:

ScenarioProblem state-sync solves
Multi-window desktop app (Tauri, Electron)State diverges between windows/processes
Multi-process architectureMain ↔ renderer processes lose sync
Backend pushes state updatesEvents arrive out of order, UI flickers
State must survive restartNeed persistence with proper invalidation

No, if you have:

  • Single-window app with no cross-process communication
  • Simple in-memory state that never leaves the process
  • Already using a solution like TanStack Query for server state

How it works ​

Stale updates are rejected. Rapid events are merged. State stays consistent. Learn more →

Explore ​

Quick example ​

Sync a Zustand store across browser tabs with persistence:

typescript
import { createRevisionSync } from '@statesync/core';
import { createZustandSnapshotApplier } from '@statesync/zustand';

// 1. Listen for "state changed" events from other tabs
const channel = new BroadcastChannel('my-sync');
const subscriber = {
  async subscribe(handler) {
    channel.onmessage = (e) => handler(e.data);
    return () => channel.close();
  },
};

// 2. Fetch current state
const provider = {
  async getSnapshot() {
    const raw = localStorage.getItem('my-state');
    return raw ? JSON.parse(raw) : { revision: '0', data: {} };
  },
};

// 3. Wire it together
const sync = createRevisionSync({
  topic: 'my-state',
  subscriber,
  provider,
  applier: createZustandSnapshotApplier(useMyStore),
});

await sync.start();

Full Quickstart →

Released under the MIT License.