Skip to main content
@livestore/adapter-web runs LiveStore in a browser. It provides:
  • makePersistedAdapter — persisted storage in the Origin Private File System (OPFS) with SharedWorker-based multi-tab leader election
  • makeInMemoryAdapter — ephemeral in-memory storage (no persistence across reloads)
  • makeSingleTabAdapter — persisted storage without SharedWorker (for browsers that don’t support it)

Installation

npm install @livestore/adapter-web

Exports

import {
  makePersistedAdapter,
  makeInMemoryAdapter,
  makeSingleTabAdapter,
  canUseSharedWorker,
} from '@livestore/adapter-web'

makePersistedAdapter

Creates a web adapter with persistent OPFS storage. Requires a dedicated worker and a shared worker. On browsers without SharedWorker support (e.g. Android Chrome), it automatically falls back to single-tab mode.
function makePersistedAdapter(options: WebAdapterOptions): Adapter

Parameters

options.worker
((options) => Worker) | (new (options) => Worker)
required
Constructor or factory for the dedicated worker. In Vite, use the ?worker import:
import LiveStoreWorker from './livestore.worker.ts?worker'
options.sharedWorker
((options) => SharedWorker) | (new (options) => SharedWorker)
required
Constructor or factory for the shared worker. Import from @livestore/adapter-web/shared-worker:
import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'
options.storage
StorageTypeEncoded
required
Where to persist data. Currently only OPFS is supported:
storage: { type: 'opfs' }
options.resetPersistence
boolean
default:"false"
Wipes all persisted data for this store on startup. Use only during development.
options.clientId
string
Stable identifier for this browser client. Defaults to a random ID stored in localStorage (shared across tabs).
options.sessionId
string
Identifier for this browser tab/window. Defaults to a random ID stored in sessionStorage (unique per tab).

Worker file setup

Create a livestore.worker.ts file that calls makeWorker:
livestore.worker.ts
import { makeWorker } from '@livestore/adapter-web/worker'
import { schema } from './schema'

makeWorker({ schema })

Full example

app.ts
import { makePersistedAdapter } from '@livestore/adapter-web'
import LiveStoreWorker from './livestore.worker.ts?worker'
import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'

export const adapter = makePersistedAdapter({
  worker: LiveStoreWorker,
  sharedWorker: LiveStoreSharedWorker,
  storage: { type: 'opfs' },
})

makeInMemoryAdapter

Creates a web adapter with no persistence. Data is lost on page reload. Ideal for tests, demos, and sandboxes.
function makeInMemoryAdapter(options?: InMemoryAdapterOptions): Adapter

Parameters

options.sync
SyncOptions
Optional sync backend. Useful when you want real-time collaboration without persistence.
options.importSnapshot
Uint8Array
Pre-populate the in-memory database from an existing snapshot.
options.clientId
string
Defaults to a random NanoID.
options.sessionId
string
Defaults to a random NanoID.

Example

import { makeInMemoryAdapter } from '@livestore/adapter-web'

const adapter = makeInMemoryAdapter()
With a sync backend:
import { makeInMemoryAdapter } from '@livestore/adapter-web'
import { makeWsSync } from '@livestore/sync-cf/client'

const adapter = makeInMemoryAdapter({
  sync: {
    backend: makeWsSync({ url: 'wss://sync.example.com' }),
  },
})

canUseSharedWorker

Returns true when the SharedWorker API is available in the current browser context. Returns false on Android Chrome and other browsers that don’t support it.
function canUseSharedWorker(): boolean
makePersistedAdapter calls this internally and falls back to makeSingleTabAdapter automatically. Use it directly only if you need to branch UI behaviour based on SharedWorker availability.

Vite configuration

If you use the Vite development server, import the polyfill in your worker file to ensure hot-reloading works correctly:
livestore.worker.ts
import '@livestore/adapter-web/worker-vite-dev-polyfill'
import { makeWorker } from '@livestore/adapter-web/worker'
import { schema } from './schema'

makeWorker({ schema })
The storage: { type: 'opfs' } option requires the browser to support the Origin Private File System API. LiveStore falls back to in-memory storage automatically in private browsing mode and other contexts where OPFS is unavailable, with a console warning.

Peer dependencies

PackageVersion
effect^3.19.19

Build docs developers (and LLMs) love