The Professional Framework for Backend Architects
From Freedom to Framework
Express gives you ultimate freedom. It is "unopinionated." This is powerful, but for large teams and complex applications, it can lead to chaos.
Every developer might structure their controllers differently. Error handling can be inconsistent. There's no standard way to manage dependencies. You have to build the entire application architecture yourself, every time.
Freedom can lead to inconsistency.
NestJS is a framework for building efficient, scalable Node.js server-side applications. It is built on top of Express (or optionally Fastify) but imposes a strong architectural structure.
It is "opinionated". It provides a blueprint for how your application should be built. This ensures consistency, maintainability, and scalability across projects and teams.
NestJS provides the architectural blueprint, so you can focus on building the features.
Modules, Controllers, and Providers
Every NestJS application is built from three main components. Understanding their roles is the key to mastering the framework.
A controller is responsible for handling incoming requests and returning responses to the client. Its job is to be the entry point for a specific URL path.
A controller should not contain complex business logic. Its primary role is to receive a request, call a service to do the actual work, and then format the response.
import { Controller, Get, Param } from '@nestjs/common';
@Controller('users') // Handles all requests to the /users path
export class UserController {
@Get(':id') // Handles GET /users/:id
findOne(@Param('id') id: string) {
// Logic to find the user will be in a service
return `This action returns user #${id}`;
}
}
A provider is a class that can be "injected" as a dependency. The most common type of provider is a Service.
A service is where your business logic lives. It's responsible for tasks like fetching data from a database, performing calculations, or calling other APIs.
import { Injectable } from '@nestjs/common';
@Injectable() // Marks this class as a provider
export class UserService {
findOne(id: number): string {
// In a real app, this would talk to a database.
return `Found user with ID ${id}.`;
}
}
This is the most important concept in NestJS. Instead of the controller creating its own `UserService`, the controller declares a dependency on it, and the NestJS runtime "injects" an instance of the service into the controller's constructor.
@Controller('users')
export class UserController {
// NestJS will automatically create and "inject" an instance of UserService
constructor(private readonly userService: UserService) {}
@Get(':id')
findOne(@Param('id') id: string): string {
// The controller now delegates the work to the service
return this.userService.findOne(+id);
}
}
This decouples your components, making them easier to test and reuse.
A module is a class decorated with `@Module()`. It provides an organizational structure for your application.
Each module encapsulates a closely related set of capabilities (e.g., a `UsersModule`, a `ProductsModule`).
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
@Module({
controllers: [UserController], // Lists all controllers in this module
providers: [UserService], // Lists all services in this module
})
export class UserModule {}
The main `AppModule` then imports these feature modules to build the complete application.
Your Architectural Assistant
The NestJS Command Line Interface is a powerful tool for scaffolding and managing your application. Install it globally.
npm install -g @nestjs/cli
To start a new project, you use the `nest new` command.
nest new my-first-nest-app
This will create a new directory, install all necessary dependencies, and generate a boilerplate project with a working `AppModule`, `AppController`, and `AppService`.
The true power of the CLI is in its "generate" (`g`) commands. It automates the creation of modules, controllers, and services, and automatically wires them up for you.
The most powerful command is `nest g resource`.
# This single command will...
nest g resource products
# ...create a `products` folder with:
# - products.module.ts
# - products.controller.ts
# - products.service.ts
# - products.entity.ts (placeholder)
# - products.dto.ts (Data Transfer Objects)
# ...and it will automatically import the new ProductsModule into your AppModule!
Your task is to use the NestJS CLI to create a new project and then generate a complete, working CRUD API for a `todos` resource. We will use the in-memory patterns from last week inside our new service.