Multi-App (forFeature)
Run multiple independent Inertia apps inside the same NestJS process using forFeature.
Register a scope
// admin.module.ts
import { Module } from '@nestjs/common';
import { InertiaModule } from '@dudousxd/nestjs-inertia';
@Module({
imports: [
InertiaModule.forFeature({
scope: 'admin',
rootView: 'inertia/admin/root.html',
vite: { entry: 'admin/client.tsx' },
share: async (req) => ({ adminUser: req.user }),
}),
],
controllers: [AdminDashboardController],
})
export class AdminModule {}Each scope gets its own InertiaService, Vite manifest, SSR loader, and shared props. Completely isolated from the default scope registered by forRoot().
Async scope registration
InertiaModule.forFeatureAsync({
scope: 'admin',
imports: [ConfigModule],
useFactory: (config: ConfigService) => ({
rootView: config.get('ADMIN_ROOT_VIEW'),
vite: { entry: 'admin/client.tsx' },
share: async (req) => ({ adminUser: req.user }),
}),
inject: [ConfigService],
})Supports useFactory, useClass, and useExisting, same as forRootAsync.
Select a scope in a controller
Use @UseInertia('scope-name') on a controller or handler to bind it to that scope.
import { Controller, Get } from '@nestjs/common';
import { Inertia, UseInertia } from '@dudousxd/nestjs-inertia';
@Controller('admin')
@UseInertia('admin')
export class AdminDashboardController {
@Get('/')
@Inertia('admin/Dashboard')
index() {
return { stats: { users: 120 } };
}
}Default scope
Controllers without @UseInertia use the default scope registered by InertiaModule.forRoot(). No decorator needed.
Shared props are scope-isolated
The share function from forRoot() does not run for forFeature scopes. The share function from a forFeature scope does not run for the default scope or other feature scopes.
Each scope is a separate Inertia universe: its own root HTML shell, its own Vite manifest, its own shared props factory.