On this page

What is NestJS? Architecture and first project

12 min read TextCh. 1 — NestJS Fundamentals

What is NestJS?

NestJS is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications. It uses TypeScript by default and is heavily inspired by Angular's architecture — if you know Angular, you will feel right at home with NestJS.

Released in 2017 by Kamil Mysliwiec, NestJS has grown to become the most popular enterprise-grade framework for Node.js backends. Its combination of decorators, modules, dependency injection, and a rich ecosystem of official packages makes it ideal for REST APIs, microservices, WebSockets, and GraphQL servers.

Why NestJS over plain Express or Fastify?

Plain Express is powerful but gives you zero structure. Teams building large applications with Express often reinvent the same architectural patterns over and over: how to organize files, how to inject dependencies, how to validate requests, how to handle errors. NestJS answers all these questions with opinionated, well-tested conventions.

Key advantages of NestJS:

  • TypeScript first — full type safety across the entire request lifecycle
  • Dependency injection — clean, testable code without manual wiring
  • Module system — feature isolation and encapsulation by default
  • Decorator-based — controllers, services, guards, and pipes declared with readable decorators
  • Platform agnostic — runs on Express or Fastify under the hood
  • Rich ecosystem — official packages for TypeORM, JWT, WebSockets, Swagger, config, and more

Core concepts at a glance

NestJS applications are composed of four building blocks:

Concept Role
Module Groups related controllers and providers
Controller Handles HTTP requests and returns responses
Provider / Service Contains business logic, injected where needed
Pipe / Guard / Interceptor Cross-cutting concerns (validation, auth, logging)

Installing and creating a project

Install the CLI globally:

npm install -g @nestjs/cli

Create a new project:

nest new bookstore-api

The CLI asks about your preferred package manager (npm, yarn, or pnpm). After installation, your project structure looks like this:

bookstore-api/
  src/
    app.controller.ts     # Root controller
    app.controller.spec.ts
    app.module.ts         # Root module
    app.service.ts        # Root service
    main.ts               # Application entry point
  test/
    app.e2e-spec.ts
    jest-e2e.json
  nest-cli.json           # CLI configuration
  tsconfig.json
  package.json

Running the application

cd bookstore-api
npm run start:dev

The start:dev script runs the application with watch mode enabled using ts-node-dev. Any file change triggers an automatic restart. Open your browser at http://localhost:3000 and you will see Hello World!.

Understanding main.ts

The main.ts file is the entry point of every NestJS application. It uses NestFactory.create() to instantiate the application from the root module and then starts listening for connections.

The bootstrap function pattern is important: it is async because NestJS initializes all providers, runs lifecycle hooks, and may perform asynchronous operations before the server is ready. Always await the listen() call.

The request lifecycle

When a request arrives at a NestJS application, it travels through several layers in a specific order:

  1. Middleware — Express/Fastify middleware (logging, body parsing)
  2. Guards — Authentication and authorization checks
  3. Interceptors (before) — Transform requests, add metadata
  4. Pipes — Validate and transform request data
  5. Controller — Route handler executes business logic
  6. Interceptors (after) — Transform responses
  7. Exception filters — Catch and format errors

Understanding this lifecycle is essential for building robust APIs. Each layer has a single responsibility, which keeps your code clean and testable.

NestJS 11 highlights

NestJS 11 (released in 2025) ships with several improvements over version 10:

  • Fastify v5 support — the high-performance HTTP adapter is fully compatible
  • Node.js 20+ requirement — takes advantage of native fetch and improved ESM support
  • Updated TypeORM and Mongoose integrations — aligned with their latest major versions
  • Improved CLI generators — better monorepo support and resource generation
  • Enhanced testing utilities — cleaner test module setup with Test.createTestingModule()

Generating resources with the CLI

One of NestJS's productivity superpowers is the nest generate command (alias nest g):

# Generate a complete CRUD resource (module + controller + service + DTOs)
nest g resource books

# Generate individually
nest g module books
nest g controller books
nest g service books

The nest g resource command is particularly useful: it asks whether you want REST, GraphQL, WebSocket, or microservice, and generates all the boilerplate including empty CRUD methods.

Project configuration

The nest-cli.json file controls the CLI behavior. The most important fields:

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "deleteOutDir": true,
    "plugins": ["@nestjs/swagger"]
  }
}

The plugins array can include the Swagger plugin, which automatically extracts type information from DTOs without requiring manual decorators on every field.

TypeScript configuration

NestJS projects use strict TypeScript settings. The key options in tsconfig.json:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "strictNullChecks": true,
    "strict": true
  }
}

experimentalDecorators and emitDecoratorMetadata are mandatory for the decorator-based dependency injection system to work correctly. Without emitDecoratorMetadata, TypeScript does not emit type information at runtime, and NestJS cannot resolve constructor parameter types automatically.

What you will build in this course

Throughout this course, you will build a Bookstore REST API step by step. By the end, you will have a fully functional backend with:

  • Books, authors, and categories resources
  • JWT authentication with refresh tokens
  • Role-based authorization
  • File uploads
  • Real-time notifications via WebSockets
  • Swagger documentation
  • Unit and integration tests
  • Environment-based configuration
  • Production-ready deployment setup

Each lesson introduces one concept and applies it directly to the bookstore project, so every piece of code you write has a concrete purpose.

Generating a project
Use the NestJS CLI to scaffold a project instantly: npm install -g @nestjs/cli && nest new my-api. The CLI supports TypeScript out of the box, and all generators (nest generate controller, nest generate service) follow the same conventions.
Node.js version
NestJS 11 requires Node.js 20 or later. Verify your version with node --version before creating a project.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

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

  // Enable CORS for frontend applications
  app.enableCors({
    origin: ['http://localhost:4200'],
    credentials: true,
  });

  // Global prefix for all routes
  app.setGlobalPrefix('api');

  await app.listen(3000);
  console.log('Application running on: http://localhost:3000');
}

bootstrap();