Skip to content

SSR

Server-side rendering with @nano_kit/router is handled by a dedicated SSR renderer package for your framework. The router itself provides the building blocks — page-level Stores$ and Head$ — while the adapter takes care of the server renderer and client hydration.

Export a Stores$ function from a page module to declare which signals should be dehydrated on the server and rehydrated on the client. The SSR renderer discovers it automatically.

Mark individual signals as hydratable using hydratable from @nano_kit/store:

import { signal, hydratable } from '@nano_kit/store'
import { useSignal } from '@nano_kit/react'
/* Tie the signal to a unique key for dehydration */
export const $data = hydratable('homeData', signal({ text: 'Hello World' }))
export function Stores$() {
return [$data]
}
export default function Home() {
const data = useSignal($data)
return <h1>{data.text}</h1>
}

For pages that use DI, Stores$ is called within the request’s InjectionContext, so you can use inject() inside it:

import { inject, hydratable } from '@nano_kit/store'
import { User$ } from './stores/user'
export function Stores$() {
const { $user } = inject(User$)
return [$user]
}

Export a Head$ function from a page module to declare per-page document metadata. See Head Management for all available tag descriptors.

import { title, meta } from '@nano_kit/router'
export function Head$() {
return [
title('Home — My App'),
meta({ name: 'description', content: 'Welcome to my app' })
]
}
export default function Home() { /* ... */ }

Head$ is also called within the request’s InjectionContext, so you can use inject() inside it:

import { inject } from '@nano_kit/store'
import { title } from '@nano_kit/router'
import { User$ } from './stores/user'
export function Head$() {
const { $user } = inject(User$)
return [
title(() => `${$user().name} — My App`)
]
}

The SSR renderer reads Head$ and injects the tags into the HTML response automatically.

The low-level setup (virtual navigation, renderer class, client hydration) is handled by the SSR renderer. See the SSR renderer docs for a complete setup guide.