db-core/collection-setup

Creating typed collections with createCollection. Adapter selection: queryCollectionOptions (REST/TanStack Query), electricCollectionOptions (ElectricSQL real-time sync), powerSyncCollectionOptions (PowerSync SQLite), rxdbCollectionOptions (RxDB), trailBaseCollectionOptions (TrailBase), localOnlyCollectionOptions, localStorageCollectionOptions. CollectionConfig options: getKey, schema, sync, gcTime, autoIndex (default off), defaultIndexType, syncMode (eager/on-demand, plus progressive for Electric). StandardSchema validation with Zod/Valibot/ArkType. Collection lifecycle (idle/loading/ready/error). Adapter-specific sync patterns including Electric txid tracking, Query direct writes, Query initial data and scoped factories, and PowerSync query-driven sync with onLoad/onLoadSubset hooks.

Install
npx skills add 'https://github.com/TanStack/db/tree/main/packages/db/skills/db-core/collection-setup'
Download bundle ↓
main · 09776a8Scanned 2026-09-17

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗
View on GitHub
← Back to SKILL.md

TrailBase Adapter Reference

Install

pnpm add @tanstack/trailbase-db-collection @tanstack/react-db trailbase

Required Config

import { createCollection } from '@tanstack/react-db'
import { trailBaseCollectionOptions } from '@tanstack/trailbase-db-collection'
import { initClient } from 'trailbase'

const trailBaseClient = initClient('https://your-trailbase-instance.com')

const todosCollection = createCollection(
  trailBaseCollectionOptions({
    recordApi: trailBaseClient.records('todos'),
    getKey: (item) => item.id,
    parse: {},
    serialize: {},
  }),
)
  • recordApi -- TrailBase Record API instance from trailBaseClient.records(tableName)
  • getKey -- extracts unique key from each item
  • parse -- field conversions from TrailBase records to collection rows
  • serialize -- field conversions from collection rows to TrailBase records

Use empty objects for parse and serialize when both shapes are identical.

Optional Config

OptionDefaultDescription
id(none)Unique collection identifier
syncModeeagereager or on-demand

Conversions (parse/serialize)

TrailBase uses different data formats (e.g. Unix timestamps). Use parse and serialize for field-level transformations.

type SelectTodo = {
  id: string
  text: string
  created_at: number // Unix timestamp from TrailBase
  completed: boolean
}

type Todo = {
  id: string
  text: string
  created_at: Date // Rich JS type for app usage
  completed: boolean
}

const collection = createCollection(
  trailBaseCollectionOptions<Todo, SelectTodo>({
    id: 'todos',
    recordApi: trailBaseClient.records('todos'),
    getKey: (item) => item.id,
    parse: {
      created_at: (ts) => new Date(ts * 1000),
    },
    serialize: {
      created_at: (date) => Math.floor(date.valueOf() / 1000),
    },
  }),
)

Real-time Subscriptions

Automatic when enable_subscriptions is enabled on the TrailBase server. No additional client config needed -- the collection subscribes to changes automatically.

Persistence Handlers

TrailBase owns onInsert, onUpdate, and onDelete. The adapter writes through the Record API and waits until subscription events confirm the affected IDs before removing the optimistic overlay. Custom mutation handlers and schema are not part of TrailBaseCollectionConfig.

Call collection.utils.cancel() to cancel the active TrailBase event reader.

Complete Example

import { createCollection, safeRandomUUID } from '@tanstack/react-db'
import { trailBaseCollectionOptions } from '@tanstack/trailbase-db-collection'
import { initClient } from 'trailbase'

const trailBaseClient = initClient('https://your-trailbase-instance.com')

type Todo = {
  id: string
  text: string
  completed: boolean
  created_at: Date
}

type SelectTodo = {
  id: string
  text: string
  completed: boolean
  created_at: number
}

const todosCollection = createCollection(
  trailBaseCollectionOptions<Todo, SelectTodo>({
    id: 'todos',
    recordApi: trailBaseClient.records('todos'),
    getKey: (item) => item.id,
    parse: {
      created_at: (ts) => new Date(ts * 1000),
    },
    serialize: {
      created_at: (date) => Math.floor(date.valueOf() / 1000),
    },
  }),
)

// Usage
todosCollection.insert({
  id: safeRandomUUID(),
  text: 'Review PR',
  completed: false,
  created_at: new Date(),
})
Referenced from SKILL.md