Reference
Architecture
Package responsibilities, dependency graph, and request lifecycle for nestjs-inertia.
Five focused packages that together implement the Inertia.js protocol for NestJS.
Package map
┌──────────────────────────────────┐
│ @dudousxd/nestjs-inertia │
│ (core) │
│ │
│ InertiaModule.forRoot() │
│ @Inertia() decorator │
│ InertiaService │
│ Version negotiation │
│ CSRF, redirects, method spoof │
└───────────┬──────────────────────┘
┌────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────────┐ ┌────────────────────┐ ┌──────────────────────────┐
│ nestjs-inertia- │ │ nestjs-inertia- │ │ nestjs-inertia- │
│ vite │ │ testing │ │ codegen │
│ │ │ │ │ │
│ Vite plugin │ │ expectInertia() │ │ CLI: codegen / doctor │
│ Dev-server HMR │ │ InertiaAssertion │ │ Emits: │
│ Manifest serving │ │ TestingModule │ │ pages.d.ts │
└─────────────────────┘ └────────────────────┘ │ routes.ts │
│ api.ts │
└──────────┬───────────────┘
│ emits
▼
┌──────────────────────────┐
│ nestjs-inertia- │
│ client │
│ │
│ @As() route naming │
│ createFetcher │
│ <Link> components │
│ SSR hydration │
└──────────────────────────┘Package responsibilities
core (@dudousxd/nestjs-inertia)
InertiaModule.forRoot(options)registers the module globally. Configures root view, version string, shared-data factory.InertiaModule.forFeature(options)registers an additional scope with isolated config and shared props.@Inertia(component)method decorator intercepts a controller return value and serializes it as an Inertia response.InertiaServiceinjectable service for programmatic Inertia renders and redirects.- Version negotiation compares
X-Inertia-Versionheader and triggers a full reload when assets change. CsrfCookieInterceptor/CsrfGuardfor CSRF protection.RedirectInterceptorconverts 302 to 303 for PUT/PATCH/DELETE per the Inertia protocol.MethodSpoofMiddlewareenables_methodfield support for HTML forms.- Auto-starts codegen watcher in development when
@dudousxd/nestjs-codegenis installed.
vite (@dudousxd/nestjs-inertia-vite)
nestInertia(options)Vite plugin for React/Vue/Svelte transforms.setupInertiaVite(app, options)attaches the Vite dev-server middleware to the NestJS Express/Fastify app.- In production, reads the Vite manifest to inject hashed asset URLs into the root view.
testing (@dudousxd/nestjs-inertia-testing)
expectInertia(response)fluent assertion chain (toRenderComponent,toHaveProp,toHaveVersion, and more).assertInertia(payload)same assertions against a raw JSON payload.InertiaTestingModule.forTest()wrapsInertiaModule.forRoot()with test defaults.createFakeInertiaRequest()/createFakeInertiaResponse()for unit tests without HTTP.- Framework matchers for Vitest and Jest via subpath imports.
codegen (@dudousxd/nestjs-codegen + @dudousxd/nestjs-inertia-codegen-extension)
The typed-client codegen lives in the standalone @dudousxd/nestjs-codegen package. This repo ships @dudousxd/nestjs-inertia-codegen-extension, the extension you register so the generated api.ts gains the Inertia router import and a typed navigate() helper. The codegen statically analyses the NestJS app and emits:
pages.d.tsmodule augmentation for typed@Inertia()and page props.routes.tstyped route map +route()helper for URL resolution.api.tsqueryOptions(),mutationOptions(),queryKey(), andinfiniteQueryOptions()for every route. Response types are wrapped inJsonify<...>by default so they reflect the JSON wire shape (Date→string); opt out withserialization: 'superjson'. Page props useParameters<typeof import(...).default>[0].
Setup diagnostics are provided by nestjs-inertia doctor (from @dudousxd/nestjs-inertia) with --fix for auto-repair.
client (@dudousxd/nestjs-inertia-client)
@As(name)sets the route name for a controller class or method (read by codegen). Auto-derived fromClassName.methodNamewhen absent.createFetcher(options)creates a typed fetch client from the generatedapi.ts.invalidate(queryClient, name, args?)invalidates TanStack Query cache by route name.hydrateClientFromInertia(page)initializes TanStack Query from the Inertia initial-page payload.- Typed
<Link>components for React, Vue 3, and Svelte with route-name autocomplete.
Request lifecycle
Browser GET /dashboard
→ NestJS router → DashboardController.index()
→ @Inertia('Dashboard') interceptor
← { user, count } (return value)
→ InertiaService serializes response
• First visit → HTML shell (Vite manifest + <div id="app" data-page="...">)
• X-Inertia → JSON { component, props, url, version }
→ Browser renders React/Vue/Svelte page via inertia entry