Skip to content

SvelteKit

The @nano_kit/svelte-kit package integrates Nano Kit with SvelteKit. It re-exports everything from @nano_kit/svelte and @nano_kit/svelte-router, and adds SvelteKit-specific helpers for store dehydration, client hydration, navigation, router-aware links, and server cookies.

Install the package using your favorite package manager:

pnpm add @nano_kit/store @nano_kit/router @nano_kit/svelte-kit

The main SvelteKit integration point is store dehydration in +page.server.ts and hydration in the matching +page.svelte.

  1. Set up the root layout

    Create a request-scoped dehydration context in the root server layout and pass its reference to the root layout component.

    // src/routes/+layout.server.ts
    import {
    setDehydrationContext
    } from '@nano_kit/svelte-kit'
    import type { LayoutServerLoad } from './$types'
    export const load: LayoutServerLoad = () => {
    const contextRef = setDehydrationContext()
    return {
    contextRef
    }
    }
    <!-- src/routes/+layout.svelte -->
    <script lang="ts">
    import { setHydrationContext } from '@nano_kit/svelte-kit'
    let { data, children } = $props()
    setHydrationContext({
    fromRef: () => data.contextRef
    })
    </script>
    {@render children()}
  2. Dehydrate page stores

    Choose whether SvelteKit should dehydrate stores during client-side navigations.

    // src/routes/characters/+page.server.ts
    import {
    dehydrate,
    isFlight
    } from '@nano_kit/svelte-kit'
    import { Stores$ } from '$lib/pages/Characters.svelte'
    import type { PageServerLoad } from './$types'
    export const load: PageServerLoad = async () => ({
    dehydrated: !isFlight() && await dehydrate(Stores$)
    })

    isFlight() skips server dehydration during browser navigation. Stores still work, but navigation-time data is fetched in the browser instead of being prepared by the SvelteKit server load.

  3. Hydrate page stores

    Pass the dehydrated page data to setHydrationContext in the page component.

    <!-- src/routes/characters/+page.svelte -->
    <script lang="ts">
    import { setHydrationContext } from '@nano_kit/svelte-kit'
    import CharactersPage from '$lib/pages/Characters.svelte'
    let { data } = $props()
    setHydrationContext({
    dehydrated: () => data.dehydrated
    })
    </script>
    <CharactersPage />

Set up navigation only when stores or components use Nano Kit router dependencies such as Location$, Navigation$, Link, or typed route navigation.

In the root server layout, provide request navigation.

// src/routes/+layout.server.ts
import { provide } from '@nano_kit/store'
import {
Location$,
Navigation$,
serverNavigation,
setDehydrationContext
} from '@nano_kit/svelte-kit'
import { routes } from '$lib/stores/router'
import type { LayoutServerLoad } from './$types'
export const load: LayoutServerLoad = () => {
const [location, navigation] = serverNavigation(routes)
const contextRef = setDehydrationContext([
provide(Location$, location),
provide(Navigation$, navigation)
])
return {
contextRef
}
}

In the root layout component, provide browser navigation.

<!-- src/routes/+layout.svelte -->
<script lang="ts">
import { provide } from '@nano_kit/store'
import {
Link,
Location$,
Navigation$,
getKitNavigation,
setHydrationContext
} from '@nano_kit/svelte-kit'
import { routes } from '$lib/stores/router'
let { data, children } = $props()
const [location, navigation] = getKitNavigation(routes)
setHydrationContext({
fromRef: () => data.contextRef,
context: [
provide(Location$, location),
provide(Navigation$, navigation)
]
})
</script>
<nav>
<Link to="home">Home</Link>
<Link to="characters">Characters</Link>
</nav>
{@render children()}

@nano_kit/svelte-kit exports CookieStore, a server adapter around SvelteKit’s cookies object. Provide it through CookieStore$ when stores use cookie-backed signals.

// src/routes/+layout.server.ts
import { provide } from '@nano_kit/store'
import {
CookieStore,
setDehydrationContext
} from '@nano_kit/svelte-kit'
import { CookieStore$ } from '@nano_kit/platform-web'
import type { LayoutServerLoad } from './$types'
export const load: LayoutServerLoad = ({ cookies }) => {
const contextRef = setDehydrationContext([
provide(CookieStore$, new CookieStore(cookies))
])
return {
contextRef
}
}

Then inject CookieStore$ in stores that use cookie-backed signals.

// src/lib/stores/session.ts
import { inject } from '@nano_kit/store'
import {
CookieStore$,
cookieStored
} from '@nano_kit/platform-web'
export function Session$() {
const cookieStore = inject(CookieStore$)
const $session = cookieStored<string | null>(cookieStore, {
name: 'session',
path: '/',
sameSite: 'lax'
}, null)
return {
$session
}
}

See SSR Cookies for the general cookie model.

  • Svelte - Svelte bindings for Nano Kit stores and dependency injection
  • Svelte Router - typed links and router-aware Svelte components
  • SSR Cookies - request-bound cookies and Set-Cookie forwarding