Skip to content

Commit db559d2

Browse files
committed
docs: april update
1 parent df7769b commit db559d2

20 files changed

Lines changed: 1950 additions & 292 deletions

File tree

website/astro.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ export default defineConfig({
110110
directory: 'router'
111111
}
112112
},
113+
{
114+
label: 'SSR',
115+
autogenerate: {
116+
directory: 'ssr'
117+
}
118+
},
113119
{
114120
label: 'Integrations',
115121
autogenerate: {

website/src/content/docs/examples/rick-and-morty.mdx

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,37 @@ sidebar:
55
order: 3
66
---
77

8-
<iframe
9-
src='https://stackblitz.com/github/TrigenSoftware/nano_kit/tree/main/examples/rick-and-morty/react-nano_kit?embed=1&file=src/App.tsx&view=both'
10-
loading='lazy'
11-
style='width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden;'
12-
title='Rick and Morty Encyclopedia built with React and Nano Kit'
13-
allow='accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking'
14-
sandbox='allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts'
15-
/>
8+
import { Tabs, TabItem } from '@astrojs/starlight/components'
9+
10+
<Tabs syncKey='example-view'>
11+
<TabItem label='React SSR' icon='seti:react'>
12+
<iframe
13+
src='https://stackblitz.com/github/TrigenSoftware/nano_kit/tree/main/examples/rick-and-morty/react-nano_kit-ssr?embed=1&file=src/App.tsx&view=both'
14+
loading='lazy'
15+
style='width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden;'
16+
title='Rick and Morty Encyclopedia built with React SSR and Nano Kit'
17+
allow='accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking'
18+
sandbox='allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts'
19+
/>
20+
</TabItem>
21+
<TabItem label='Next.js App Router' icon='vercel'>
22+
<iframe
23+
src='https://stackblitz.com/github/TrigenSoftware/nano_kit/tree/main/examples/rick-and-morty/next-app-nano_kit-ssr?embed=1&file=src/app/page.tsx&view=both'
24+
loading='lazy'
25+
style='width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden;'
26+
title='Rick and Morty Encyclopedia built with Next.js App Router and Nano Kit'
27+
allow='accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking'
28+
sandbox='allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts'
29+
/>
30+
</TabItem>
31+
<TabItem label='Next.js Pages Router' icon='vercel'>
32+
<iframe
33+
src='https://stackblitz.com/github/TrigenSoftware/nano_kit/tree/main/examples/rick-and-morty/next-pages-nano_kit-ssr?embed=1&file=src/pages/index.tsx&view=both'
34+
loading='lazy'
35+
style='width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden;'
36+
title='Rick and Morty Encyclopedia built with Next.js Pages Router and Nano Kit'
37+
allow='accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking'
38+
sandbox='allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts'
39+
/>
40+
</TabItem>
41+
</Tabs>

website/src/content/docs/getting-started/index.mdx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,18 @@ unsub()
5050
| [@nano_kit/store](/store) | Signals-based state management library. |
5151
| [@nano_kit/query](/query) | Data fetching and caching library, built on @nano_kit/store. |
5252
| [@nano_kit/router](/router) | Routing library, built on @nano_kit/store. |
53+
| [@nano_kit/ssr](/ssr) | Base package for building framework-specific SSR adapters. |
5354

5455
### Framework Adapters
5556

5657
| Adapter | Description |
5758
|---------|-------------|
58-
| [@nano_kit/react](/integrations/react) | React bindings for @nano_kit/store. |
59-
| [@nano_kit/react-router](/integrations/react-router) | React bindings for @nano_kit/router. |
59+
| [@nano_kit/react](/integrations/react) | React integration for @nano_kit/store. |
60+
| [@nano_kit/react-router](/integrations/react-router) | React integration for @nano_kit/router. |
61+
| [@nano_kit/next-router](/integrations/next-router) | Next.js integration for @nano_kit/router. |
62+
| [@nano_kit/react-ssr](/integrations/react-ssr) | React SSR adapter for @nano_kit/ssr. |
6063

61-
<Aside>Nano Kit is currently in **alpha**. More adapters are coming later.</Aside>
64+
<Aside>Nano Kit is currently in **beta**. More adapters are coming later.</Aside>
6265

6366
## Motivation
6467

website/src/content/docs/integrations/index.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ sidebar:
77

88
| Adapter | Description |
99
|---------|-------------|
10-
| [@nano_kit/react](/integrations/react) | React bindings for @nano_kit/store. |
11-
| [@nano_kit/react-router](/integrations/react-router) | React bindings for @nano_kit/router. |
10+
| [@nano_kit/react](/integrations/react) | React integration for @nano_kit/store. |
11+
| [@nano_kit/react-router](/integrations/react-router) | React integration for @nano_kit/router. |
12+
| [@nano_kit/next-router](/integrations/next-router) | Next.js integration for @nano_kit/router. |
13+
| [@nano_kit/react-ssr](/integrations/react-ssr) | React SSR adapter for @nano_kit/ssr. |
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
---
2+
title: Next.js Router
3+
description: "Integrate @nano_kit/router with Next.js using @nano_kit/next-router."
4+
sidebar:
5+
order: 5
6+
---
7+
8+
import { Tabs, TabItem, Code } from '@astrojs/starlight/components'
9+
10+
The `@nano_kit/next-router` package provides Next.js integration for `@nano_kit/router`. It re-exports everything from `@nano_kit/react-router` and adds Next.js-specific navigation providers, a router-aware `Link`, and helpers for the Pages Router.
11+
12+
For shared router APIs such as [`useLocation`](/integrations/react-router#uselocation), [`useNavigation`](/integrations/react-router#usenavigation), [`usePaths`](/integrations/react-router#usepaths), [`useListenLinks`](/integrations/react-router#usenavigationlistenlinks--uselistenlinks), see the [React Router integration](/integrations/react-router).
13+
14+
## Installation
15+
16+
Install the package using your favorite package manager:
17+
18+
<Tabs syncKey='pkg'>
19+
<TabItem label='pnpm' icon='pnpm'>
20+
<Code frame='none' lang='bash' code='pnpm add @nano_kit/store @nano_kit/router @nano_kit/react @nano_kit/next-router' />
21+
</TabItem>
22+
<TabItem label='Yarn' icon='seti:yarn'>
23+
<Code frame='none' lang='bash' code='yarn add @nano_kit/store @nano_kit/router @nano_kit/react @nano_kit/next-router' />
24+
</TabItem>
25+
<TabItem label='npm' icon='seti:npm'>
26+
<Code frame='none' lang='bash' code='npm install @nano_kit/store @nano_kit/router @nano_kit/react @nano_kit/next-router' />
27+
</TabItem>
28+
</Tabs>
29+
30+
## Setup
31+
32+
Like `@nano_kit/react-router`, this package works with route definitions declared in `AppContext.routes`.
33+
34+
```tsx
35+
import { routes } from '@/stores/router'
36+
37+
declare module '@nano_kit/router' {
38+
interface AppContext {
39+
routes: typeof routes
40+
}
41+
}
42+
```
43+
44+
The Next.js setup differs slightly between the App Router and the Pages Router.
45+
46+
### App Router
47+
48+
Use `NextNavigation` in the root layout to create navigation for the current RSC request and provide `Location$` / `Navigation$` to client components.
49+
50+
```tsx
51+
import type { Metadata } from 'next'
52+
import {
53+
FlightDetector,
54+
HydrationProvider
55+
} from '@nano_kit/react'
56+
import { NextNavigation } from '@nano_kit/next-router'
57+
import { routes } from '@/stores/router'
58+
59+
declare module '@nano_kit/router' {
60+
interface AppContext {
61+
routes: typeof routes
62+
}
63+
}
64+
65+
export const metadata: Metadata = {
66+
title: 'My App'
67+
}
68+
69+
export default function RootLayout({ children }: {
70+
children: React.ReactNode
71+
}) {
72+
return (
73+
<FlightDetector>
74+
<NextNavigation
75+
routes={routes}
76+
prerenderable
77+
>
78+
<HydrationProvider>
79+
<html lang='en'>
80+
<body>{children}</body>
81+
</html>
82+
</HydrationProvider>
83+
</NextNavigation>
84+
</FlightDetector>
85+
)
86+
}
87+
```
88+
89+
If a page dehydrates stores on the server, wrap that page's dehydration boundary in its own `NextNavigation`. This ensures client-side flight renders still have a current navigation context.
90+
91+
```tsx
92+
import { Dehydration } from '@nano_kit/react'
93+
import { NextNavigation } from '@nano_kit/next-router'
94+
import { routes } from '@/stores/router'
95+
import CharactersPage, { Stores$ } from '@/ui/pages/Characters'
96+
97+
export default function Page() {
98+
return (
99+
<NextNavigation routes={routes}>
100+
<Dehydration stores={Stores$}>
101+
<CharactersPage />
102+
</Dehydration>
103+
</NextNavigation>
104+
)
105+
}
106+
```
107+
108+
### Pages Router
109+
110+
Use `NextNavigationProvider` in `_app.tsx` to provide navigation in client components, then hydrate store data through `HydrationProvider`.
111+
112+
```tsx
113+
import type { AppProps } from 'next/app'
114+
import { HydrationProvider } from '@nano_kit/react'
115+
import { NextNavigationProvider } from '@nano_kit/next-router'
116+
import { routes } from '@/stores/router'
117+
118+
declare module '@nano_kit/router' {
119+
interface AppContext {
120+
routes: typeof routes
121+
}
122+
}
123+
124+
export default function App({ Component, pageProps }: AppProps) {
125+
return (
126+
<NextNavigationProvider routes={routes}>
127+
<HydrationProvider dehydrated={pageProps.dehydrated}>
128+
<Component {...pageProps} />
129+
</HydrationProvider>
130+
</NextNavigationProvider>
131+
)
132+
}
133+
```
134+
135+
For SSR data loading in `getServerSideProps`, use `virtualNavigationContext` together with `dehydrate`.
136+
137+
```tsx
138+
import type { GetServerSideProps } from 'next'
139+
import { dehydrate } from '@nano_kit/store'
140+
import { virtualNavigationContext } from '@nano_kit/next-router'
141+
import { routes } from '@/stores/router'
142+
import CharactersPage, { Stores$ } from '@/ui/pages/Characters'
143+
144+
export const getServerSideProps: GetServerSideProps = async (context) => {
145+
const dehydrated = await dehydrate(
146+
Stores$,
147+
virtualNavigationContext(context.resolvedUrl, routes)
148+
)
149+
150+
return {
151+
props: {
152+
dehydrated
153+
}
154+
}
155+
}
156+
157+
export default function Page() {
158+
return <CharactersPage />
159+
}
160+
```
161+
162+
## Next Specifics
163+
164+
### `NextNavigation`
165+
166+
`NextNavigation` is an async RSC component for the App Router. It creates navigation for the current request, provides `Location$` and `Navigation$`, and renders `NextNavigationProvider` on the client.
167+
168+
Server-side `navigation.push()` and `navigation.replace()` are mapped to Next.js redirects. The `prerenderable` prop skips [Next.js `connection()`](https://nextjs.org/docs/app/api-reference/functions/connection) and allows the route to stay statically prerenderable, but in that mode `searchParams` are not available during server render.
169+
170+
```tsx
171+
import { NextNavigation } from '@nano_kit/next-router'
172+
173+
export default function Layout({ children }: {
174+
children: React.ReactNode
175+
}) {
176+
return (
177+
<NextNavigation
178+
routes={routes}
179+
prerenderable
180+
>
181+
{children}
182+
</NextNavigation>
183+
)
184+
}
185+
```
186+
187+
### `NextNavigationProvider`
188+
189+
`NextNavigationProvider` is the client-side provider used by the Pages Router and by `NextNavigation` after hydration. It creates an `InjectionContext` with `Location$` and `Navigation$` only when a fresh client navigation context is needed.
190+
191+
```tsx
192+
import { NextNavigationProvider } from '@nano_kit/next-router'
193+
194+
<NextNavigationProvider routes={routes}>
195+
<App />
196+
</NextNavigationProvider>
197+
```
198+
199+
### `Link`
200+
201+
`Link` is a typed wrapper around `next/link`. It supports route-aware `to` and `params` props, but also accepts plain `href` when needed.
202+
203+
Use it inside `NextNavigation` or `NextNavigationProvider`.
204+
205+
```tsx
206+
'use client'
207+
import { Link } from '@nano_kit/next-router'
208+
209+
export function Nav() {
210+
return (
211+
<nav>
212+
<Link to='characters'>Characters</Link>
213+
<Link to='character' params={{ id: '42' }}>
214+
Rick
215+
</Link>
216+
<Link href='/about'>About</Link>
217+
</nav>
218+
)
219+
}
220+
```
221+
222+
### `redirect` & `notFound`
223+
224+
These helpers are for the Pages Router.
225+
226+
- `redirect(context, permanent?)` returns a Next.js `{ redirect: ... }` if redirection was triggered during dehydration.
227+
- `notFound(value)` returns `{ notFound: true }` when the value is falsy.
228+
229+
```tsx
230+
import type { GetServerSideProps } from 'next'
231+
import { contextDehydrate } from '@nano_kit/store'
232+
import {
233+
notFound,
234+
redirect,
235+
virtualNavigationContext
236+
} from '@nano_kit/next-router'
237+
import { routes } from '@/stores/router'
238+
import { User$ } from '@/stores/user'
239+
import UserPage, { Stores$ } from '@/ui/pages/User'
240+
241+
export const getServerSideProps: GetServerSideProps = async (nextContext) => {
242+
const [context, dehydrated] = await contextDehydrate(
243+
Stores$,
244+
virtualNavigationContext(nextContext.resolvedUrl, routes)
245+
)
246+
const { $user } = context.get(User$)
247+
248+
return notFound($user()) ?? redirect(context) ?? {
249+
props: {
250+
dehydrated
251+
}
252+
}
253+
}
254+
255+
export default function Page() {
256+
return <UserPage />
257+
}
258+
```

0 commit comments

Comments
 (0)