omnistate-react
v0.1.1
Published
React hooks for OmniState — zero-drop cross-tab and cross-device state sync
Maintainers
Readme
omnistate-react
React hook for OmniState — zero-drop cross-tab and cross-device state sync.
Hand off any user state (cart, form, session) to another device with a single URL. No backend required.
Install
npm install omnistate-reactQuick start
import { useOmniState } from 'omnistate-react'
function CartPage() {
const { state, setState, push, autoPull, isReady } = useOmniState<CartState>('cart', {
apiKey: import.meta.env.VITE_OMNISTATE_API_KEY,
schema: { items: { type: 'array' }, coupon: { type: 'string' } },
defaultState: { items: [], coupon: '' },
})
// Auto-pull on mount — does nothing if no token in URL
useEffect(() => { autoPull() }, [])
const handleShare = async () => {
const { url } = await push()
// Show url as QR code, copy to clipboard, send via SMS, etc.
}
if (!isReady) return null
return (
<div>
<button onClick={handleShare}>Continue on another device</button>
</div>
)
}API
useOmniState<T>(namespace, options)
| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string | — | OmniState API key. Required for push/pull. |
| schema | Schema | — | Field allowlist — only listed fields are synced. |
| defaultState | Partial<T> | {} | Initial state on first mount. |
| ttl | number | 1800 | Session TTL in seconds (max depends on tier). |
| relayUrl | string | relay.omnistate.dev | Override the relay URL. |
| enableBroadcast | boolean | true | Enable cross-tab sync via BroadcastChannel. |
Returns:
| Property | Type | Description |
|---|---|---|
| state | T | Current CRDT state — updates reactively. |
| setState | (partial: Partial<T>) => void | Merge partial state (CRDT-safe). |
| push | (baseUrl?) => Promise<{ url, token }> | Encrypt and push state to relay. Returns handoff URL. |
| pull | (token, key) => Promise<void> | Pull and decrypt from relay using token + key. |
| autoPull | () => Promise<boolean> | Read token + key from URL fragment and pull. Returns true if pulled. |
| getUsage | () => Promise<UsageInfo> | Fetch monthly usage from relay. |
| isReady | boolean | True once CRDT doc and BroadcastChannel are connected. |
How it works
- Device A calls
push()→ state is encrypted client-side (AES-256-GCM) → ciphertext stored on relay → returns a URL with the decryption key in the#fragment(never sent to server) - Device B opens the URL →
autoPull()reads the fragment → downloads and decrypts the state → CRDT merge into local doc
The relay holds only ciphertext. The encryption key never leaves the URL fragment.
Get an API key
Free at omnistate.dev — 500 handoffs/month, no credit card.
Packages
| Package | Description |
|---|---|
| omnistate-react | React hook (this package) |
| omnistate-sdk | Vanilla JS client |
| omnistate-core | CRDT engine (Yjs) |
License
MIT
