Tulip Logo IconTulip
Local (Beta)

Introduction

Beta strategy for building opt-in local-first modules in Tulip with TanStack DB.

Tulip Local is the proposed local-first layer in @tulip-systems/query/tanstack-db. It builds on TanStack DB so modules can get optimistic updates, more responsive UI state, and live query ergonomics without forcing that model on every feature.

This section is intentionally a beta planning area. It documents the strategy first so we can refine the implementation and API before promoting it as a stable part of the core package.

Goals

  • make local-first modules an opt-in capability
  • improve optimistic UI flows for edit-heavy screens
  • support both full local collections and subset-driven loading
  • keep server-side business logic reusable between suspense queries and live queries
  • make Tulip components work with both the default server-first flow and local-first flow

Current prototype inputs

The current direction is based on what already exists in the repo today:

  • collection prototypes built with @tanstack/react-db and @tanstack/query-db-collection
  • shared query client helpers from @tulip-systems/query/tanstack-query
  • syncMode: "on-demand" experiments for child collections
  • local filter, sorting, and pagination helpers in @tulip-systems/query/tanstack-db

Core principles

1. Local is optional

Collections and local-first behavior must never be required for a Tulip module. A module should still be able to ship with the existing server-first query and mutation approach.

2. The server stays the source of truth

Local state improves UX, but it does not replace server validation, authorization, or persistence rules.

3. One module can support multiple loading strategies

Some modules can load a full working set into a local collection. Others need on-demand subsets because the data volume is too large. Tulip should support both without forcing a different UI API per module.

4. Shared filter logic matters more than shared transport

The same filter and sorting rules should be reusable whether data comes from a suspense query, a live query, or an on-demand collection subset.

What needs to be standardized

  • when a module should choose local-first at all
  • how syncMode fits into module and component APIs
  • how loadSubsetOptions gets normalized into server-friendly inputs
  • how live queries can still work when data is paginated or loaded incrementally

Suggested direction

The current prototypes suggest a split model:

  • use full local collections for bounded datasets and highly interactive screens
  • use on-demand collections when the working set is too large to hydrate up front
  • add shared helpers in @tulip-systems/query/tanstack-db so server filters, sorting, and pagination contracts are not reimplemented per module
  • treat paginated live data as a separate strategy from the current fully local table strategy

Next pages

On this page