Skip to content

Latest commit

 

History

History

README.md

@nano_kit/next-router

ESM-only package NPM version Dependencies status Install size Build status Coverage status

Next.js integration for @nano_kit/router. Provides navigation primitives for both client components and React Server Components, a router-aware <Link> component, and helpers for the Pages Router.

Installation

pnpm add @nano_kit/store @nano_kit/router @nano_kit/react @nano_kit/next-router
# or
npm install @nano_kit/store @nano_kit/router @nano_kit/react @nano_kit/next-router
# or
yarn add @nano_kit/store @nano_kit/router @nano_kit/react @nano_kit/next-router

Quick Start

App Router

Layout (RSC)

Wrap the app with NextNavigation — it sets up navigation on the server and hydrates on the client:

// app/layout.tsx
import { NextNavigation } from '@nano_kit/next-router'
import { routes } from '@/stores/router'

// Define global types for routes
declare module '@nano_kit/router' {
  interface AppContext {
    routes: typeof routes
  }
}

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <NextNavigation routes={routes}>
      <html lang="en">
        <body>
          <Nav />
          {children}
        </body>
      </html>
    </NextNavigation>
  )
}

Client Component

Use the router-aware Link:

'use client'
import { Link } from '@nano_kit/next-router'

export function Nav() {
  return (
    <nav>
      <Link to='characters'>Characters</Link>
      <Link to='episodes'>Episodes</Link>
      <Link to='character' params={{ id: '42' }}>Rick</Link>
    </nav>
  )
}

Page with Stores (RSC)

Use Dehydration to prefetch store data on the server and hydrate it on the client. Each Dehydration must be directly wrapped in its own NextNavigation — during client-side navigations ("flight" requests) Next.js only renders the requested page segment, not the root layout, so stores need their own navigation context:

// app/characters/page.tsx
import { Dehydration } from '@nano_kit/react'
import { NextNavigation } from '@nano_kit/next-router'
import { routes } from '@/stores/router'
import { CharactersPage, Stores$ } from '@/ui/pages/Characters'

export default function Page() {
  return (
    <NextNavigation routes={routes}>
      <Dehydration stores={Stores$}>
        <CharactersPage />
      </Dehydration>
    </NextNavigation>
  )
}

Pages Router

Layout

Use NextNavigationProvider in _app.tsx:

// pages/_app.tsx
import type { AppProps } from 'next/app'
import { HydrationProvider } from '@nano_kit/react'
import { NextNavigationProvider } from '@nano_kit/next-router'
import { routes } from '@/stores/router'

// Define global types for routes
declare module '@nano_kit/router' {
  interface AppContext {
    routes: typeof routes
  }
}

export default function App({ Component, pageProps }: AppProps) {
  return (
    <NextNavigationProvider routes={routes}>
      <HydrationProvider dehydrated={pageProps.dehydrated}>
        <Component {...pageProps} />
      </HydrationProvider>
    </NextNavigationProvider>
  )
}

Page with SSR

Use virtualNavigationContext and dehydrate in getServerSideProps to prefetch data on the server:

// pages/characters.tsx
import type { GetServerSideProps } from 'next'
import { dehydrate } from '@nano_kit/store'
import { virtualNavigationContext } from '@nano_kit/router'
import { routes } from '@/stores/router'
import { CharactersPage, Stores$ } from '@/ui/pages/Characters'

export const getServerSideProps: GetServerSideProps = async (context) => {
  const dehydrated = await dehydrate(
    Stores$,
    virtualNavigationContext(context.resolvedUrl, routes)
  )

  return { props: { dehydrated } }
}

export default function Page() {
  return <CharactersPage />
}

Documentation

For comprehensive guides, API reference, and integration patterns, visit the documentation website.