Svelte
@ginjou/svelte is the base Svelte adapter for Ginjou.
It exposes Ginjou's core contracts through Svelte's setContext/getContext, adds TanStack Query-backed data hooks, and includes the controller layer for resource-oriented pages.
The package targets Svelte 5 and uses runes throughout.
Installation
Install @ginjou/svelte together with @tanstack/svelte-query.
Ginjou uses TanStack Query for query and mutation state in Svelte, so both packages are part of the base setup.
pnpm add @ginjou/svelte @tanstack/svelte-query
yarn add @ginjou/svelte @tanstack/svelte-query
npm install @ginjou/svelte @tanstack/svelte-query
bun add @ginjou/svelte @tanstack/svelte-query
Setup
The smallest useful Svelte setup starts with two contexts:
defineQueryClientContext()for TanStack Query state.defineFetchersContext()for data access.
Register them once near the app root so every Ginjou composable reads the same shared contexts.
<script lang="ts">
import { defineFetcher } from '@ginjou/core'
import { defineFetchersContext, defineQueryClientContext } from '@ginjou/svelte'
const { children } = $props()
defineQueryClientContext({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000,
},
},
})
defineFetchersContext({
default: defineFetcher({
async getList() {
return {
data: [],
total: 0,
}
},
async getOne({ id }) {
return {
data: { id },
}
},
}),
})
</script>
{@render children()}
From there, add router, auth, authz, notifications, i18n, realtime, and resources only when the app needs them.
Contexts
@ginjou/svelte keeps all shared contexts explicit through Svelte's setContext/getContext.
Each defineXContext() call registers one app-level implementation of a Ginjou contract. Composables, controllers, and lower-level helpers read from those contexts later.
| Provider | When to add it | Guide |
|---|---|---|
defineQueryClientContext | Always for the data layer | Data |
defineFetchersContext | Always for the data layer | Data |
defineAuthContext | When the app supports login, logout, or identity | Authentication |
defineAuthzContext | When the app checks permissions or access rules | Authorization |
defineRouterContext | When navigation, current location, or controller route sync matter | Router |
defineI18nContext | When the app translates text or switches locale | I18n |
defineNotificationContext | When the app shows toast-like feedback | Notifications |
defineRealtimeContext | When queries subscribe or mutations publish realtime events | Realtime |
defineResourceContext | When the app defines shared resource metadata | Resources |
Most Svelte apps start with query client and fetchers, then add the other contexts only when they become necessary.
This page only covers the integration shape. Use the linked guides for the full contract and behavior of each context.
Runes
@ginjou/svelte is built for Svelte 5 and uses runes throughout.
Query and mutation results from @tanstack/svelte-query are reactive by default through Svelte 5 signals. Accessing .data, .isLoading, .isPending, and other result fields in reactive contexts such as $derived or templates works without any extra wrapping.
Controller state fields like currentPage, perPage, filters, sorters, and search are exposed as plain reactive properties that can be read and assigned directly.
<script lang="ts">
import { useList } from '@ginjou/svelte'
const listPage = useList({
resource: 'posts',
})
function nextPage() {
listPage.currentPage += 1
}
</script>
MaybeAccessor<T> means the prop accepts either a plain value (T) or an accessor function (() => T). Use the function form when the prop value depends on reactive state.
<script lang="ts">
import { useGetOne } from '@ginjou/svelte'
const { id } = $props()
const postQuery = useGetOne(() => ({
resource: 'posts',
id,
}))
</script>
Ecosystem
These packages extend @ginjou/svelte with third-party library integrations.