Querying with TanStack DB
super-line syncs; it does not query. For joins, live queries, and optimistic mutations, hand a row collection to TanStack DB via the first-party @super-line/tanstack-db adapter. TanStack DB is the client query engine; super-line is the server-authoritative source under it.
Wire a collection into TanStack
import { createCollection, createLiveQueryCollection, eq } from '@tanstack/db'
import { superLineCollectionOptions } from '@super-line/tanstack-db'
const users = createCollection(superLineCollectionOptions(client, api, 'users'))
const messages = createCollection(
superLineCollectionOptions(client, api, 'messages', { query: { filter: eq('channelId', 'general') } }),
)superLineCollectionOptions derives getKey from the contract, subscribes over super-line for the given query, and maps each TanStack transaction to one atomic super-line batch — the ack resolves the optimistic commit; an error rolls it back.
Joins and live queries
// a client-side join, denormalizing author names onto messages — updates incrementally as rows sync
const feed = createLiveQueryCollection((q) =>
q.from({ m: messages })
.join({ u: users }, ({ m, u }) => eq(u.id, m.authorId), 'inner')
.select(({ m, u }) => ({ id: m.id, text: m.text, author: u.name })),
)Joins, ordering, and incremental recomputation all run in the browser over the synced rows — TanStack's query predicates are never pushed to the server. What crosses the wire is set per collection by the query: IR filter you hand to superLineCollectionOptions (above, messages is narrowed to one channel; users syncs whole).
React
Use useLiveQuery from @tanstack/react-db with the same query builder:
import { useLiveQuery } from '@tanstack/react-db'
const { data } = useLiveQuery((q) =>
q.from({ m: messages }).join({ u: users }, ({ m, u }) => eq(u.id, m.authorId), 'inner'),
)Optimism
TanStack DB applies mutations optimistically — locally, instantly — then reconciles against the server ack. On error it rolls back. That's the layer client.collection(n) deliberately doesn't provide: the raw sync layer is non-optimistic (a write appears when the server confirms it), and TanStack adds optimism on top.
When you don't need TanStack
For a simple filtered list, useCollection or a raw client.collection(n).subscribe(query) is enough — no query engine required. Reach for TanStack DB when you need joins, multi-collection live queries, or optimistic UX.
Run it
examples/collections shows a messages ⋈ users join and optimistic writes with rollback against a real server, and examples/collections-chat is a full Slack-like app built on the adapter.