Local-first

Share durable local mutations and synchronization semantics across web, Expo, and desktop clients while keeping product policy explicit.

Supported approaches

Atomic local mutations

available

Commit product state and its outbound mutation together so crashes cannot split the two records.

Packages

@playstack/local-first

Frameworks and integrations

Portable synchronization

available

Push idempotent mutation batches and apply cursor-based change pages under an explicit runtime lease.

Frameworks and integrations

Platform storage

available

Persist the same contracts with IndexedDB in browsers or Expo SQLite in React Native applications.

Frameworks and integrations

integration

IndexedDB

Browser persistence and Web Locks coordination for the local-first engine.

framework

React

Headless domain bindings plus optional Chakra application and admin compositions, with server authority kept outside the client.

framework

Next.js

Compose Playstack server contracts, React bindings, SSR handoff, and route adapters at the Next.js application edge.

framework

Expo

Use Playstack authentication and local-first contracts with Expo SecureStore, SQLite, and React Native lifecycle adapters.

Package reference

@playstack/local-first

Share the synchronization contract

@playstack/local-first is runtime-neutral. A product supplies its entities, mutation and change vocabulary, conflict policies, storage, transport, runtime coordination, clock, and identifiers.

ts
const client = createLocalFirstClient({
  definition,
  storage,
  transport,
  runtime,
  scope: () => ({ type: 'account', id: currentAccountId }),
  clock,
  ids,
})

await client.mutate('draft.save', draft)
await client.sync()

Every mutation updates local state and the durable outbox within one storage transaction. Synchronization then acquires a scope lease, pushes a bounded batch, records retry or conflict outcomes, and applies pull pages and cursors atomically.

Adapt real platform differences

Use @playstack/local-first-indexeddb for browser and PWA persistence. Use @playstack/local-first-expo for Expo SQLite storage and React Native lifecycle coordination. Both satisfy the same core conformance contracts without pretending IndexedDB and SQLite have identical native APIs.

Tauri SQLite, shared React bindings, and a Nest server package remain planned. Applications continue to own authentication, server change sources, attachments, retention, and background-execution policy.

Keep invariant-heavy writes online

Local-first support does not make payments, limited inventory, or other invariant-heavy commands automatically safe offline. Products choose which mutations can be accepted speculatively and how conflicts are surfaced or recovered.

Go

Playstack Pro tag
OriginsPricingBlogNewsletterChangelogStatusRoadmap
ContributorsCommunityIn Use ShowcaseCase StudiesPartnersSponsors
FAQsSupportContact

© 2026 Playstack. All rights reserved.

With OSS
Terms of ServicePrivacy PolicyCookie PolicyImprint

By

Commune Software