Project structure

Application bootstrap, main modules, and entry point.

This guide describes how the NestJS application is initialized and how modules connect.

Entry point

The src/host/main.ts file configures OpenAPI documentation, global error filter, and starts the server. CORS, cookies, and rate limit live in applyHttpMiddleware (src/host/bootstrap/). Details: HTTP middleware. Core projects (without auth/cron) stay slim — the CLI removes optional imports and blocks when features were not selected.

typescript
import { applyHttpMiddleware } from '@/host/bootstrap/apply-http-middleware';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { defineDocumentation } from './open-api/define-documentation';
import { ErrorsFilter } from './filters/errors.filter';
import { HttpAdapterHost } from '@nestjs/core';
import { ILoggingService } from '@/domain/common/ilogging.service';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  applyHttpMiddleware(app);

  await defineDocumentation(app);

  const { httpAdapter } = app.get(HttpAdapterHost);
  app.useGlobalFilters(new ErrorsFilter(httpAdapter, app.get(ILoggingService)));

  await app.listen(process.env.PORT || 3000);
}

bootstrap();

With authentication (kl-nest add auth or selected in new): global guards (AuthGuard, ProfilesGuard). Cookies are already handled by applyHttpMiddleware.

With cron/event jobs (kl-nest add cron / add events): infrastructure under src/core/background-services/ and JobsModule.register() in AppModule (empty arrays in Default; sample handlers in CRUD).

AppModule imports environment validation and feature modules. In the CRUD Example template, PersonModule is already registered; in the Default template, you add modules as you create resources.

typescript
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      validate: (config) => envSchema.parse(config),
    }),
    JobsModule.register({
      eventHandlers: [], // or sample handlers in CRUD template
      cronJobs: [],
    }),
    PersonModule, // CRUD template
  ],
})
export class AppModule {}

Every project includes src/host/jobs/ with JobsModule.register(). Pass handler classes in eventHandlers and cronJobs; JobsBootstrapService subscribes to events and starts cron jobs on OnModuleInit (controlled by CRON_JOBS_ENABLED).

typescript
JobsModule.register({
  eventHandlers: [InactivePersonHandler],
  cronJobs: [CreatePersonJob, DeleteInactiveJob],
})

In the example template, CRON_JOBS_ENABLED=true in .env.example. Tune BOOTSTRAP_DELAY_MS if dependencies need warm-up before jobs. See Cron and Event Jobs.

In the application module, organize jobs by type and specialty:

text
src/application/<resource>/jobs/
├── cron/                          # CronJobHandlerBase
│   └── my-job.ts
└── events/
    └── <resource>/                # EventJob aggregate
        ├── <resource>-event.job.ts
        └── <specialty>/           # event + handler
            ├── my-event.event.ts
            └── my-event.handler.ts

Person example: jobs/cron/create-person.job.ts and jobs/events/person/inactive-person/.

text
AppModule
├── ConfigModule (Zod env)
├── HealthCheckModule     # opt-in: kl-nest add health
├── SecurityModule        # opt-in: auth
├── AuthModule            # opt-in: auth
└── PersonModule          # CRUD template
    └── ControllerModule
        ├── MappingProvider
        └── InfraModule
            ├── ILoggingService
            ├── ICacheService      # opt-in: cache / OAuth2 / cron
            ├── IRedLockService    # opt-in: cache with cron
            └── RepositoryModule
                └── DatabaseModule

MappingProvider ensures all mappings are registered before any handler runs:

typescript
@Injectable()
export class MappingProvider {
  constructor() {
    PersonMapper.createMap();
  }
}

Generated projects use the @/ alias pointing to src/. Real import example:

typescript
import { Person } from '@/domain/entities/person/person';
import { AutoMapper } from '@/core/tools/mapping';
import { IPersonRepository } from '@/domain/repositories/iperson.repository';

Bun

bash
bun run start:dev
bun run start:prod
bun test
bun test --watch
bun run migration:generate
bun run migration:run
bun run migration:revert

npm / pnpm — use npm run or pnpm run with the same script names. Tests use Vitest; migration:generate, migration:run, and migration:revert use node --import ts-node/register/transpile-only.

Koala Nest

A facilitator for building NestJS APIs with DDD architecture. Code copied into your repository — readable, adaptable, and under your control.

Creator

igordrangel.com.br

Design, back-end, and product strategy.

Quick Commands

Global CLI and scripts in the generated project

  • bun install -g @koalarx/nest
  • kl-nest new
  • kl-nest add cache
  • bun run migration:run # CRUD template
  • kl-nest --help
© 2026 Koala NestBuilt for NestJS developers and AI-assisted workflows.