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

Local Adapters Reference

Both adapters are included in the core package.

Install

pnpm add @tanstack/react-db

localOnlyCollectionOptions

In-memory only. No persistence. No cross-tab sync.

Required Config

import {
  createCollection,
  localOnlyCollectionOptions,
} from '@tanstack/react-db'

const collection = createCollection(
  localOnlyCollectionOptions({
    getKey: (item) => item.id,
  }),
)
  • getKey -- extracts unique key from each item

Optional Config

OptionDefaultDescription
idUUIDUnique collection identifier
schema(none)StandardSchema validator
initialData(none)Array of items to populate on creation
onInsert(none)Handler before confirming inserts
onUpdate(none)Handler before confirming updates
onDelete(none)Handler before confirming deletes

Direct Mutations

collection.insert({ id: 'theme', mode: 'dark' })
collection.update('theme', (draft) => {
  draft.mode = 'light'
})
collection.delete('theme')

initialData

localOnlyCollectionOptions({
  id: 'ui-state',
  getKey: (item) => item.id,
  initialData: [
    { id: 'sidebar', isOpen: false },
    { id: 'theme', mode: 'light' },
  ],
})

acceptMutations in Manual Transactions

When using createTransaction, call collection.utils.acceptMutations(transaction) in mutationFn:

import { createTransaction } from '@tanstack/react-db'

const tx = createTransaction({
  mutationFn: async ({ transaction }) => {
    // Handle server mutations first, then:
    localData.utils.acceptMutations(transaction)
  },
})
tx.mutate(() => {
  localData.insert({ id: 'draft-1', data: '...' })
})
await tx.commit()

localStorageCollectionOptions

Persists to localStorage. Cross-tab sync via storage events. Survives reloads.

Required Config

import {
  createCollection,
  localStorageCollectionOptions,
} from '@tanstack/react-db'

const collection = createCollection(
  localStorageCollectionOptions({
    storageKey: 'app-user-prefs',
    getKey: (item) => item.id,
  }),
)
  • storageKey -- localStorage key for all collection data
  • getKey -- extracts unique key from each item

Optional Config

OptionDefaultDescription
idFrom storage keylocal-collection:${storageKey}
schema(none)StandardSchema validator
storagelocalStorageCustom storage (sessionStorage or any localStorage-compatible API)
storageEventApiwindowEvent API for cross-tab sync
onInsert(none)Handler on insert
onUpdate(none)Handler on update
onDelete(none)Handler on delete

Using sessionStorage

localStorageCollectionOptions({
  id: 'session-data',
  storageKey: 'session-key',
  storage: sessionStorage,
  getKey: (item) => item.id,
})

Custom Storage Backend

Provide any object with getItem, setItem, removeItem:

const encryptedStorage = {
  getItem: (key) => {
    const v = localStorage.getItem(key)
    return v ? decrypt(v) : null
  },
  setItem: (key, value) => localStorage.setItem(key, encrypt(value)),
  removeItem: (key) => localStorage.removeItem(key),
}
localStorageCollectionOptions({
  id: 'secure',
  storageKey: 'enc-key',
  storage: encryptedStorage,
  getKey: (i) => i.id,
})

acceptMutations

Same as LocalOnly -- call collection.utils.acceptMutations(transaction) in manual transactions.


Comparison

FeatureLocalOnlyLocalStorage
PersistenceNone (in-memory)localStorage
Cross-tab syncNoYes
Survives reloadNoYes
PerformanceFastestFast
Size limitsMemory~5-10MB

Complete Example

import {
  createCollection,
  localOnlyCollectionOptions,
  localStorageCollectionOptions,
} from '@tanstack/react-db'
import { z } from 'zod'

// In-memory UI state
const modalState = createCollection(
  localOnlyCollectionOptions({
    id: 'modal-state',
    getKey: (item) => item.id,
    initialData: [
      { id: 'confirm-delete', isOpen: false },
      { id: 'settings', isOpen: false },
    ],
  }),
)

// Persistent user prefs
const userPrefs = createCollection(
  localStorageCollectionOptions({
    id: 'user-preferences',
    storageKey: 'app-user-prefs',
    getKey: (item) => item.id,
    schema: z.object({
      id: z.string(),
      theme: z.enum(['light', 'dark', 'auto']),
      language: z.string(),
      notifications: z.boolean(),
    }),
  }),
)

modalState.update('settings', (draft) => {
  draft.isOpen = true
})
userPrefs.insert({
  id: 'current-user',
  theme: 'dark',
  language: 'en',
  notifications: true,
})
Referenced from SKILL.md