Skip to content

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-bootstrap

When 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 CaseFit
HTTP APIs on ExpressBuilt-in server/express, security, session, and openapi steps.
Vercel-compatible NestJS appsNestFactory, ExpressAdapter, and NestExpressApplication remain in the app entrypoint.
Shared platform startup defaultsCompose a stable sequence once and reuse it across apps.
Step-order testsUse the testing subpath without starting a real HTTP server.

Quick Start

typescript
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

ImportPurpose
@breadstone/archipel-platform-bootstrapPlatformApplication, builder types, API step, config keys
@breadstone/archipel-platform-bootstrap/server/expressExpress body parsers and compression middleware
@breadstone/archipel-platform-bootstrap/securityCORS, Helmet, content-security-policy, rate limiting
@breadstone/archipel-platform-bootstrap/sessionExpress-compatible session middleware
@breadstone/archipel-platform-bootstrap/openapiSwaggerFeatureDiscovery.setupMultiDocumentSwagger() step
@breadstone/archipel-platform-bootstrap/testingLightweight 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.

typescript
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 {}
EntryKeys
PLATFORM_SERVER_CONFIG_ENTRIESPORT
PLATFORM_SECURITY_CONFIG_ENTRIESAPP_CORS_ORIGIN, APP_RATE_LIMIT_WINDOW_MS, APP_RATE_LIMIT_MAX_REQUESTS
PLATFORM_SESSION_CONFIG_ENTRIESAUTH_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

StepOptionsPurpose
useApi()IApiStepOptionsGlobal prefix, validation, and global exception filters.
useExpressServer()IExpressServerStepOptionsJSON parser, URL-encoded parser, and compression middleware.
useSecurity()ISecurityStepOptionsCORS, Helmet, content security policy, and rate limiting.
useSession()ISessionStepOptionsExpress-compatible sessions using typed config entries.
useOpenApi()IOpenApiStepOptionsMulti-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.

typescript
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.

typescript
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.

Released under the MIT License.