platform-bootstrap
Generic NestJS application composition for Archipel APIs. It replaces repeated app-level bootstrap code with a fluent PlatformApplication builder and tree-shakable subpath steps.
The package starts from an existing Nest application. Your entrypoint still calls NestFactory.create(), selects the HTTP adapter, and keeps the concrete application type visible. platform-bootstrap then applies reusable startup steps for API defaults, Express middleware, security, sessions, OpenAPI, and tests.
Package: @breadstone/archipel-platform-bootstrap
npm install @breadstone/archipel-platform-bootstrapWhen to Use
Use this package when multiple NestJS apps need the same startup shape but still need explicit control over their adapter and deployment target.
| Use Case | Fit |
|---|---|
| HTTP APIs on Express | Built-in server/express, security, session, and openapi steps. |
| Vercel-compatible NestJS apps | NestFactory, ExpressAdapter, and NestExpressApplication remain in the app entrypoint. |
| Shared platform startup defaults | Compose a stable sequence once and reuse it across apps. |
| Step-order tests | Use the testing subpath without starting a real HTTP server. |
Quick Start
import { ConsoleLogger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter, NestExpressApplication } from '@nestjs/platform-express';
import { PlatformApplication, useApi } from '@breadstone/archipel-platform-bootstrap';
import { useExpressServer } from '@breadstone/archipel-platform-bootstrap/server/express';
import { useSecurity } from '@breadstone/archipel-platform-bootstrap/security';
import { useSession } from '@breadstone/archipel-platform-bootstrap/session';
import { useOpenApi } from '@breadstone/archipel-platform-bootstrap/openapi';
import { AppModule } from './AppModule';
async function main(): Promise<void> {
const app = await NestFactory.create<NestExpressApplication>(AppModule, new ExpressAdapter(), {
logger: new ConsoleLogger({ prefix: 'API', colors: true, forceConsole: true, compact: true, sorted: true }),
});
await PlatformApplication.from(app)
.use(useApi({ prefix: 'api' }))
.use(useExpressServer({ json: { limit: '1mb' }, urlEncoded: { extended: true, limit: '1mb' } }))
.use(useSecurity({ contentSecurityPolicy: 'swagger-compatible' }))
.use(useSession())
.use(useOpenApi())
.listenFromConfig({ fallbackPort: 3000 });
}
void main();For a full application setup, see the Application Bootstrap guide.
Entry Points
| Import | Purpose |
|---|---|
@breadstone/archipel-platform-bootstrap | PlatformApplication, builder types, API step, config keys |
@breadstone/archipel-platform-bootstrap/server/express | Express body parsers and compression middleware |
@breadstone/archipel-platform-bootstrap/security | CORS, Helmet, content-security-policy, rate limiting |
@breadstone/archipel-platform-bootstrap/session | Express-compatible session middleware |
@breadstone/archipel-platform-bootstrap/openapi | SwaggerFeatureDiscovery.setupMultiDocumentSwagger() step |
@breadstone/archipel-platform-bootstrap/testing | Lightweight bootstrap test application helpers |
Configuration
Register the config entries in the root module so startup validation and configuration discovery see the same keys the steps read at runtime.
import { Module } from '@nestjs/common';
import {
ConfigModule,
EnvironmentConfigStrategy,
} from '@breadstone/archipel-platform-configuration';
import {
PLATFORM_SECURITY_CONFIG_ENTRIES,
PLATFORM_SERVER_CONFIG_ENTRIES,
PLATFORM_SESSION_CONFIG_ENTRIES,
} from '@breadstone/archipel-platform-bootstrap';
@Module({
imports: [
ConfigModule.forRoot({
strategyFactory: () => new EnvironmentConfigStrategy(),
}),
ConfigModule.register('platform-bootstrap/server', PLATFORM_SERVER_CONFIG_ENTRIES),
ConfigModule.register('platform-bootstrap/security', PLATFORM_SECURITY_CONFIG_ENTRIES),
ConfigModule.register('platform-bootstrap/session', PLATFORM_SESSION_CONFIG_ENTRIES),
],
})
export class AppModule {}| Entry | Keys |
|---|---|
PLATFORM_SERVER_CONFIG_ENTRIES | PORT |
PLATFORM_SECURITY_CONFIG_ENTRIES | APP_CORS_ORIGIN, APP_RATE_LIMIT_WINDOW_MS, APP_RATE_LIMIT_MAX_REQUESTS |
PLATFORM_SESSION_CONFIG_ENTRIES | AUTH_SESSION_SECRET, AUTH_SESSION_SECURE, AUTH_SESSION_MAX_AGE |
listenFromConfig() resolves the HTTP port from PORT, then APP_PORT, then the provided fallback.
Built-In Steps
| Step | Options | Purpose |
|---|---|---|
useApi() | IApiStepOptions | Global prefix, validation, and global exception filters. |
useExpressServer() | IExpressServerStepOptions | JSON parser, URL-encoded parser, and compression middleware. |
useSecurity() | ISecurityStepOptions | CORS, Helmet, content security policy, and rate limiting. |
useSession() | ISessionStepOptions | Express-compatible sessions using typed config entries. |
useOpenApi() | IOpenApiStepOptions | Multi-document Swagger UI discovery and setup. |
Composition Model
The platform builder uses bootstrap steps that receive a PlatformBootstrapContext and call next() to continue the pipeline. Built-in use* helpers are normal step factories, so application-specific setup can live beside them without introducing a new NestJS module.
import { PlatformBootstrapStep } from '@breadstone/archipel-platform-bootstrap';
export const useCustomBootstrap = (): PlatformBootstrapStep => {
return async function customBootstrapStep(context, next): Promise<void> {
context.app.enableShutdownHooks();
await next();
};
};Step factories should use the use* naming convention and option interfaces should end in StepOptions. The shared pattern is documented in Bootstrap Pattern.
Testing
Use the testing subpath when the behavior under test is bootstrap composition rather than HTTP integration.
import { describe, expect, it } from 'vitest';
import { PlatformApplication, useApi } from '@breadstone/archipel-platform-bootstrap';
import { createPlatformTestApplication } from '@breadstone/archipel-platform-bootstrap/testing';
describe('bootstrap', (): void => {
it('initializes after applying API defaults', async (): Promise<void> => {
const app = createPlatformTestApplication();
await PlatformApplication.from(app)
.use(useApi({ prefix: 'api' }))
.initialize();
expect(app.calls).toContain('setGlobalPrefix');
expect(app.calls.at(-1)).toBe('init');
});
});Current Scope
The first implementation targets Express-compatible NestJS HTTP applications and keeps NestFactory in the consuming entrypoint. Fastify, serverless handler exports, and standalone worker bootstrap steps are planned as additive subpaths.