skills/tanstack/db/svelte-db

svelte-db

Installation
SKILL.md

This skill builds on db-core. Read it first for collection setup, query builder, and mutation patterns.

TanStack DB — Svelte 5

Setup

<script lang="ts">
import { useLiveQuery, eq, not } from "@tanstack/svelte-db"

const todosQuery = useLiveQuery((q) =>
  q
    .from({ todo: todoCollection })
    .where(({ todo }) => not(todo.completed))
    .orderBy(({ todo }) => todo.created_at, "asc")
)
</script>

{#if todosQuery.isLoading}
  <div>Loading...</div>
{:else}
  <ul>
    {#each todosQuery.data as todo (todo.id)}
      <li>{todo.text}</li>
    {/each}
  </ul>
{/if}

@tanstack/svelte-db re-exports everything from @tanstack/db.

Hook

useLiveQuery

Returns a reactive object with getter properties:

// Query function — access via dot notation
const query = useLiveQuery((q) => q.from({ todo: todoCollection }))
// query.data, query.isLoading, query.status, etc.

// With reactive deps — use GETTER FUNCTIONS
let minPriority = $state(5)
const query = useLiveQuery(
  (q) =>
    q
      .from({ todo: todoCollection })
      .where(({ todo }) => gt(todo.priority, minPriority)),
  [() => minPriority],
)

// Config object
const query = useLiveQuery({
  query: (q) => q.from({ todo: todoCollection }),
  gcTime: 60000,
})

// Pre-created collection
const query = useLiveQuery(preloadedCollection)

Svelte-Specific Patterns

Destructuring with $derived

// WRONG — breaks reactivity
const { data, isLoading } = useLiveQuery(...)

// CORRECT — use dot notation
const query = useLiveQuery(...)
// Access: query.data, query.isLoading

// CORRECT — wrap with $derived if you need destructuring
const query = useLiveQuery(...)
const { data, isLoading } = $derived(query)

Props in dependency arrays

<script lang="ts">
  let { userId }: { userId: number } = $props()

  const todosQuery = useLiveQuery(
    (q) => q.from({ todo: todoCollection })
             .where(({ todo }) => eq(todo.userId, userId)),
    [() => userId]
  )
</script>

Common Mistakes

CRITICAL Passing values instead of getter functions in deps

Wrong:

let filter = $state('active')
const query = useLiveQuery(
  (q) =>
    q
      .from({ todo: todoCollection })
      .where(({ todo }) => eq(todo.status, filter)),
  [filter],
)

Correct:

let filter = $state('active')
const query = useLiveQuery(
  (q) =>
    q
      .from({ todo: todoCollection })
      .where(({ todo }) => eq(todo.status, filter)),
  [() => filter],
)

In Svelte 5, deps must be getter functions. Passing values directly captures them at creation time — changes won't trigger re-execution.

Source: docs/framework/svelte/overview.md

HIGH Direct destructuring breaks reactivity

Wrong:

const { data, isLoading } = useLiveQuery((q) =>
  q.from({ todo: todoCollection }),
)

Correct:

const query = useLiveQuery((q) => q.from({ todo: todoCollection }))
// Use query.data, query.isLoading

Direct destructuring captures values at creation time. Use dot notation or wrap with $derived.

Source: packages/svelte-db/src/useLiveQuery.svelte.ts

See also: db-core/live-queries/SKILL.md — for query builder API.

See also: db-core/mutations-optimistic/SKILL.md — for mutation patterns.

Weekly Installs
1
Repository
tanstack/db
GitHub Stars
3.7K
First Seen
Mar 25, 2026
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
warp1