Skip to main content
This page covers the core reactive API of bijection-svelte. Everything here works in any Svelte app — SvelteKit, Vite + Svelte, or any other setup. Make sure you’ve called setupBijection() in a root layout first — see Overview.

Two clients

Bijection Svelte talks to your backend through two clients, and the one you use decides what’s available: BijectionClient is the live WebSocket client that setupBijection() opens — the useQuery / useMutation / useAction helpers are thin Svelte wrappers around it, and you can retrieve it directly with getBijectionClient() / useBijectionClient(). BijectionHttpClient is a stateless fetch-based client for single calls from server code or scripts — see One-time calls. Live subscriptions and optimistic updates are WebSocket-only, and optimistic updates apply to mutations only.

Queries

Use useQuery() to subscribe to a Bijection query with automatic real-time updates. When the data changes on the server, your component re-renders automatically.
The returned object is reactive and has the following shape:

Options

  • initialData — pre-loaded data for SSR/hydration, avoids the loading state (see SSR with initialData)
  • keepPreviousData — when true, keeps displaying the previous result while new data loads after args change

Skipping queries

You can conditionally skip a query by returning 'skip' from the arguments function. This is useful when a query depends on some condition, like authentication state or user input.
When a query is skipped, isLoading will be false, error will be null, and data will be undefined.

Mutations & Actions

Use useMutation() and useAction() to get callable functions for your Bijection mutations and actions. Both use the module-level singleton (getBijectionClient()) internally, so they work in .svelte components and plain .ts / .js files — anywhere after setupBijection() has been called.
Actions are similar to mutations but can have side effects like calling third-party APIs:

Optimistic updates

Optimistic updates let you update the UI immediately when a mutation is called, without waiting for the server to respond. Pass an optimisticUpdate callback in the mutation options at the call site to update the local query cache.
Inside the optimisticUpdate callback, use store.setQuery() to update the local cache for a specific query. The arguments are:
  1. Query reference — the query to update (e.g. api.user.get)
  2. Query arguments — must match the arguments used by the active useQuery() subscription
  3. New value — the optimistic data to display immediately
If the mutation fails, the optimistic update is automatically rolled back and the UI reverts to the server state.

Client access

getBijectionClient() — universal client access

getBijectionClient() retrieves the client from a module-level singleton. It works anywhere — .svelte components, plain .ts utility files, service layers, async callbacks — as long as setupBijection() has been called first. This is the recommended way to access the client outside of the layout where setupBijection() returns it directly.

useBijectionClient() — Svelte context alternative

useBijectionClient() retrieves the same client from Svelte context via getContext(). It only works during component initialization — inside .svelte files or code called synchronously from a component’s <script> block. Both functions return the same BijectionClient instance.

Using mutations in utility files

useMutation() and useAction() work in plain .ts files too, since they use the module-level singleton:
src/lib/services/tasks.ts
Then call these functions from any component without plumbing the client through:
The .svelte.ts file extension enables Svelte 5 runes ($state, $derived, $effect) but does not make getContext() work outside components. If you need the client in a plain .ts file, use getBijectionClient(), not useBijectionClient().

One-time calls

useQuery keeps a live subscription open. When you instead need a single result with no ongoing binding — a SvelteKit load function, a form action, an endpoint, or a one-off script — use the stateless BijectionHttpClient, which runs query / mutation / action over fetch with no WebSocket.
In SvelteKit, the createBijectionHttpClient() helper builds one with per-request auth wired in. The HTTP client supports one-shot calls only — no subscriptions and no optimistic updates. Mutations and actions have no “live” form to opt out of: useMutation() and useAction() are already one-shot calls (thin wrappers over the WebSocket client), so they cover writes in both reactive and non-reactive code.

Paginated queries

For queries that return large datasets, use usePaginatedQuery() to load results incrementally. This hook manages cursor-based pagination automatically and provides a loadMore function to fetch additional pages.

Options

  • initialNumItems (required) — number of items to load on the first page
  • initialData — optional initial data for SSR/hydration
  • keepPreviousData — when true, keeps previous results visible while loading new data after args change
You can also skip a paginated query by returning 'skip' from the arguments function, just like with useQuery().

API reference

Functions and types exported from bijection-svelte: Authentication exports (setupAuth, useAuth, and related types) are documented on the Authentication page.