Skip to content

Svelte integration

LiveStore’s Svelte bindings expose a single helper, createStore, which binds store.query into Svelte’s reactivity. When you call store.query inside markup or $effect, query results automatically re-run when LiveStore emits updates, and requests are cancelled on teardown via Svelte’s abort signal.

<script lang="ts">
import { makePersistedAdapter } from '@livestore/adapter-web'
import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'
import { queryDb } from '@livestore/livestore'
import { createStore } from '@livestore/svelte'
import LiveStoreWorker from './livestore.worker.ts?worker'
import { schema, tables } from './schema.ts'
const adapter = makePersistedAdapter({
storage: { type: 'opfs' },
worker: LiveStoreWorker,
sharedWorker: LiveStoreSharedWorker,
})
const store = await createStore<typeof schema>({
adapter,
schema,
storeId: 'default',
})
const todos$ = queryDb(tables.todos.where({ completed: false }), {
label: 'todos',
})
</script>
<ul>
{#each store.query(todos$) as todo (todo.id)}
<li>{todo.text}</li>
{/each}
</ul>
  • createStore is async; instantiate it where you have access to the adapter (e.g. route load, onMount, or a top-level module when running in the browser).
  • store.query opts into Svelte reactivity when called inside $effect or markup. Outside reactive contexts, you can still use store.subscribe directly.
  • Works with the Web adapter out of the box. For SSR routes, construct the store on the client since @livestore/adapter-web is browser-only.

See the Svelte TodoMVC example for a complete app.