LiveStore Documentation

repository·main·Indexed 25 days ago

https://github.com/livestorejs/livestore

A client-centric data layer providing a reactive embedded SQLite database with real-time synchronization. It features a reactive query layer, offline-first workflows, and multi-platform adapters for web, mobile, server/edge, and desktop. The ecosystem includes specialized packages like @livestore/common-cf for Effect RPC communication within Cloudflare Durable Objects and @livestore/adapter-web for web integration.

Tokens
122.1K
Snippets
160
Records
732
Agent score
84%

What's inside LiveStore

  1. Overview of LiveStore capabilities

    main

    LiveStore is a client-centric data layer designed to replace state management libraries like Redux or MobX. It provides a reactive embedded SQLite database with real-time synchronization capabilities.

    Key features include:

    • Reactive Query Layer: Full SQLite support for instant queries.
    • Multi-platform Adapters: Support for web, mobile, server/edge, and desktop.
    • Offline-First: Built for true offline workflows.
    • Data Modeling: Flexible schema management and custom merge conflict resolution.
    • Synchronization: Sync via supported providers (e.g., Cloudflare) or custom implementations using event-sourcing.
  2. Overview of the Web Adapter

    main

    The @livestore/adapter-web is designed for browser environments. It provides a robust storage and synchronization layer using the following technologies:

    • Storage: Uses SQLite WASM with OPFS (Origin Private File System) for persistent browser storage.
    • Concurrency: Runs in Web Workers and SharedWorkers to enable coordination across multiple browser tabs.
    • Persistence: Utilizes an OPFS Access Handle Pool VFS for data persistence.
    • Connectivity: Supports WebSocket connections for synchronization and developer tools.
  3. Overview of @livestore/webmesh

    main

    @livestore/webmesh is a library designed to connect multiple nodes (such as browser windows, tabs, workers, or threads) in a network-like topology. It enables the establishment of communication channels between these nodes.

    Channel Types

    • ProxyChannel: A virtual channel that proxies messages along edges via hop nodes.
    • DirectChannel: An end-to-end channel that supports transferable objects (e.g., Uint8Array).
    • BroadcastChannel: A virtual channel that broadcasts messages to all connected nodes.

    Both ProxyChannel and DirectChannel provide TCP-like properties: they have unique names across the network, support auto-reconnection, ensure ordered messages, and are reliable (buffering messages and acknowledging each one).

  4. Overview of @livestore/sync-cf

    main
    @livestore/sync-cf is a synchronization package designed for Cloudflare environments. It aims to provide a flexible, efficient, and idiomatic way to sync data using Cloudflare abstractions like Durable Objects (DOs), D1, and various transport mechanisms. It is designed to allow Durable Objects to hibernate when possible to minimize CPU billing while maintaining reactivity.
  5. Understand LiveStore Delivery Composition and Workspace Structure

    main

    LiveStore uses a dual-repository composition model where 'Core' and 'Contrib' repositories are materialized into a single workspace for development.

    Repository Roles

    • Core: Owns the engine, shared foundations, primary framework integrations, primary browser/Cloudflare adapters, Cloudflare sync, and shared framework primitives.
    • Contrib: Owns selected framework integrations, additional platform adapters, additional sync providers, devtools surfaces, GraphQL integration, CLI, and examples.

    Workspace Materialization

    Development uses the mr fetch --apply command to materialize member repositories under a repos/ directory as filesystem symlinks. This allows tools like Bun, pnpm, genie, Astro/Starlight, and TypeDoc to read across repository boundaries.

    Note: A fresh clone of the Core repository can install dependencies, typecheck, and run tests without materialization. Materialization is only required for regenerating sources (e.g., via Genie).

  6. Understand the Store API surface and behavior

    main

    A LiveStore instance (identified by a storeId) provides a unified surface for interacting with a single object or domain. The API is designed around two core principles:

    1. Synchronous Reads: store.query runs against the session's in-memory SQLite synchronously. It does not return a Promise and does not require a loading state, providing an immediate local source of truth.
    2. Instant Writes: store.commit validates and materializes changes locally, refreshes affected queries, and returns synchronously. Persistence and synchronization with the leader happen asynchronously in the background.

    Note on Error Handling: If a commit fails locally, the store shuts down rather than throwing an error back to the caller.

  7. Understand Cloudflare Sync Provider Topology

    main

    The Cloudflare Sync Provider uses a specific topology where a client connects to a Cloudflare Worker, which in turn manages a Durable Object (DO) per storeId. The Durable Object acts as the central arbiter for pushes and fans out live pull streams to subscribers.

    Topology Flow: client (SyncBackend impl) ──ws | http | do-rpc──▶ CF worker ──▶ Durable Object (per storeId)

  8. Understand the Web Topology Worker Graph

    main

    LiveStore's web runtime uses a multi-layered worker architecture to manage state and synchronization across multiple browser tabs. The topology consists of:

    1. Tabs (Main Thread): Each tab maintains a client session and an in-memory SQLite instance. Tabs communicate with the Shared Worker via an Effect RpcClient (SharedWorkerRpcs).
    2. Shared Worker: Acts as a mediator. It parses its storeId from self.name. It holds no state of its own but manages the connection to the current leader.
    3. Leader Worker: A dedicated worker (livestore-worker-<storeId>-<sessionId>) that hosts the makeLeaderThreadLayer. This worker is spawned by the leader-elect tab.

    Communication flows from Tabs $\rightarrow$ Shared Worker $\rightarrow$ Leader Worker.

  9. Understand Clients and Sessions

    main

    LiveStore distinguishes between clients and sessions:

    • Client: A logical group of client sessions on one device or runtime that share local data. It is identified by a randomly generated clientId.
    • Client session: A single running instance within a client (e.g., a specific browser tab). It is identified by a sessionId (which persists across tab reloads in web environments). Each session hosts a store and its own reactivity graph.
  10. Experimental: Use Facts for Constraints

    main

    Warning: This feature is experimental and not part of the shipping contract.

    Facts are key/value constraints that an event can set, unset, require, or read. They are intended for ordering constraints, compaction, and conflict detection in next-gen sync.

    Currently, facts are not wired into materialization; the materializer context's currentFacts is a constant empty Map.

  11. Architecture of the Web Email Client Example

    main

    The Web Email Client example demonstrates a partial synchronization pattern using multiple stores to partition data between the browser and Cloudflare.

    Data Partitioning Strategy

    • Mailbox Store (Singleton): A single store with ID mailbox-root. It manages global metadata including labels, threadIndex, threadLabels, and uiState. It handles events like v1.LabelCreated, v1.ThreadAdded, and v1.UiStateSet.
    • Thread Store (Multi-Instance): Multiple stores with IDs following the pattern thread-{id}. Each instance manages data specific to a single thread, including thread, messages, and threadLabels. It handles events like v1.ThreadCreated, v1.MessageAdded, and v1.ThreadLabelApplied.

    Synchronization Flow

    1. Browser to Cloudflare: Stores synchronize via WebSockets to their respective Cloudflare Durable Objects (MailboxClientDO for the singleton mailbox and ThreadClientDO for individual threads).
    2. Cross-Store Synchronization: When a ThreadClientDO publishes an event (e.g., v1.ThreadCreated), it is sent to a Cloudflare Queue (cross-store-events).
    3. Event Processing: A Worker (Queue Consumer) consumes these events and calls methods on the MailboxClientDO (such as addThread(), applyThreadLabel(), or removeThreadLabel()) to ensure the singleton Mailbox Store stays in sync with the distributed Thread Stores.