Quickstart
Get state-sync running in under 5 minutes.
Installation
bash
# Core engine
npm install @statesync/core
# Pick a framework adapter
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)
# Optional
npm install @statesync/tauri # Tauri v2 transport
npm install @statesync/persistence # Offline cache + cross-tab syncCore concepts
Topic
A topic is a non-empty string that identifies a piece of state (e.g., 'settings', 'cart'). Each topic has its own revision counter and syncs independently.
The three parts
| Part | Interface | Role |
|---|---|---|
| Subscriber | { subscribe(handler) => unsubscribe } | Delivers invalidation events |
| Provider | { getSnapshot() => SnapshotEnvelope } | Returns the latest state |
| Applier | { apply(snapshot) => void } | Writes state into your store |
Basic example
typescript
import { createRevisionSync, createConsoleLogger } from '@statesync/core';
interface AppSettings {
theme: 'light' | 'dark';
language: string;
}
// Subscriber: listens for invalidation events
const subscriber = {
async subscribe(handler) {
const channel = new BroadcastChannel('settings-sync');
channel.onmessage = (e) => handler(e.data);
return () => channel.close();
}
};
// Provider: fetches the latest snapshot
const provider = {
async getSnapshot() {
const res = await fetch('/api/settings');
return res.json(); // { revision: "42", data: { theme, language } }
}
};
// Applier: updates local state
let localState: AppSettings = { theme: 'light', language: 'en' };
const applier = {
apply(snapshot) {
localState = snapshot.data;
}
};
const sync = createRevisionSync({
topic: 'settings',
subscriber,
provider,
applier,
logger: createConsoleLogger({ debug: true }),
});
await sync.start();With Pinia (Vue)
typescript
import { createRevisionSync } from '@statesync/core';
import { createPiniaSnapshotApplier } from '@statesync/pinia';
import { useSettingsStore } from './stores/settings';
const store = useSettingsStore();
const sync = createRevisionSync({
topic: 'settings',
subscriber: mySubscriber,
provider: myProvider,
applier: createPiniaSnapshotApplier(store, {
mode: 'patch',
omitKeys: ['isLoading'], // Don't sync UI state
}),
});
await sync.start();With Redux (React)
typescript
import { createRevisionSync } from '@statesync/core';
import { createReduxSnapshotApplier, withSnapshotHandling } from '@statesync/redux';
import { configureStore } from '@reduxjs/toolkit';
import { rootReducer } from './store';
const store = configureStore({
reducer: withSnapshotHandling(rootReducer),
});
const sync = createRevisionSync({
topic: 'settings',
subscriber: mySubscriber,
provider: myProvider,
applier: createReduxSnapshotApplier(store, {
mode: 'patch',
omitKeys: ['isLoading'],
}),
});
await sync.start();With Zustand (React)
typescript
import { createRevisionSync } from '@statesync/core';
import { createZustandSnapshotApplier } from '@statesync/zustand';
import { useSettingsStore } from './stores/settings';
const sync = createRevisionSync({
topic: 'settings',
subscriber: mySubscriber,
provider: myProvider,
applier: createZustandSnapshotApplier(useSettingsStore, {
mode: 'patch',
omitKeys: ['isLoading'],
}),
});
await sync.start();With Tauri
typescript
import { createTauriRevisionSync } from '@statesync/tauri';
import { listen } from '@tauri-apps/api/event';
import { invoke } from '@tauri-apps/api/core';
const sync = createTauriRevisionSync({
topic: 'settings',
listen,
invoke,
eventName: 'settings:invalidated',
commandName: 'get_settings',
applier: myApplier,
});
await sync.start();Complete Tauri setup
This is frontend-only. For the full Rust backend + TypeScript frontend example, see Vue + Pinia + Tauri.
Stopping sync
typescript
sync.stop();
// After stop(), the handle is dead — create a new one to restartNext steps
- Protocol — how revision-based sync works
- Writing state — UI-to-backend write patterns
- Multi-window patterns — multi-tab and multi-window setups
- Lifecycle — API reference for
RevisionSyncHandle - Examples — runnable code samples
