Skip to main content

First Steps with NestJS

NestJS organizes backend applications using a modular structure inspired by enterprise patterns. In this practical guide, you will learn how to install the CLI, instantiate a new project, understand its internal architecture, and build your own modules, controllers, and services.


1. Architecture and Component Foundations​

Before writing code or generating files with the CLI, it is essential to understand how key components interact within a NestJS module:

Main Component Breakdown:​

  • Module (@Module): The fundamental organizational unit in NestJS. It groups related controllers and providers (services), defining dependency boundaries and enabling a scalable modular architecture.
  • Controller (@Controller): Responsible for handling external HTTP requests on specific routes (e.g., /users), extracting parameters or body payloads, and invoking corresponding service logic.
  • Service (@Injectable): Contains pure business logic (calculations, transformations, database calls, or third-party service calls). Services are decorated with @Injectable() to be automatically injected via NestJS Dependency Injection.

2. Practical Development Guide (Step-by-Step)​

1

Global installation of NestJS CLI

The NestJS CLI (Command Line Interface) automates project creation and component generation following Nest architecture best practices.

Terminal
npm install -g @nestjs/cli
Why use the CLI

The CLI avoids manual configuration of TypeScript, Webpack/SWC, ESLint, and Jest, while maintaining a clean and standardized structure across projects.

2

Creating the base project

Run the nest new command to initialize a new project named my-nest-app:

Terminal
nest new my-nest-app

During execution, the CLI will prompt you to select a package manager. Select npm (or yarn / pnpm based on your preference).

3

Inspecting project file structure

Navigate to the newly created directory and inspect the generated files:

Terminal
cd my-nest-app

The resulting structure is organized as follows:

File structure
my-nest-app/
├── src/
│ ├── app.controller.spec.ts # Unit tests for main controller
│ ├── app.controller.ts # Base controller with test route ('/')
│ ├── app.module.ts # Root application module
│ ├── app.service.ts # Base service with simple methods
│ └── main.ts # Entry point (starts HTTP server)
├── test/
│ └── app.e2e-spec.ts # End-to-end integration tests
├── nest-cli.json # Nest CLI internal configuration
├── package.json # Dependencies and run scripts
└── tsconfig.json # TypeScript compiler configuration

Explanation of key files inside src/:

  • main.ts: Uses NestFactory.create(AppModule) to instantiate the app and start the server on port 3000 by default.
  • app.module.ts: Application assembly root where root controllers and providers are registered.
  • app.controller.ts: Contains basic HTTP handlers (e.g., GET /).
  • app.service.ts: Returns simple responses (such as "Hello World!").
4

Running the application in development mode

Start the local server in watch mode so it automatically reloads upon saving changes:

Terminal
npm run start:dev

Open your browser at http://localhost:3000 to verify the application responds correctly.

Changing port in main.ts

If port 3000 is occupied on your machine, you can modify src/main.ts:

src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
// Instantiate Nest application using root module
const app = await NestFactory.create(AppModule);

// Set HTTP server listening port (e.g., 3001)
await app.listen(3001);
}
bootstrap();
5

Modular generation using CLI

To build an isolated feature (e.g., user management), generating its three core layers is recommended: Module, Controller, and Service.

Open a new terminal tab and enter the following commands:

Terminal
# 1. Generate users module
nest generate module users

# 2. Generate users controller
nest generate controller users

# 3. Generate users service
nest generate service users
CLI Shortcuts

You can use short command aliases in terminal: nest g mo users, nest g co users, and nest g s users.

6

Implementing Users Code

Examine the generated code in src/users/ and implement basic communication logic between layers:

src/users/users.service.ts
import { Injectable } from '@nestjs/common';

// Decorator marking class as injectable by NestJS IoC container
@Injectable()
export class UsersService {
// Simulated in-memory collection representing data source
private users = [
{ id: 1, name: 'Alice', email: 'alice@icesi.edu.co' },
{ id: 2, name: 'Bob', email: 'bob@icesi.edu.co' },
];

// Method to return all registered users
findAll() {
return this.users;
}

// Method to return a specific user by ID
findOne(id: number) {
return this.users.find(user => user.id === id);
}
}
src/users/users.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { UsersService } from './users.service';

// Decorator defining base HTTP route '/users' for all requests in this controller
@Controller('users')
export class UsersController {
// Dependency injection: Nest automatically injects UsersService instance
constructor(private readonly usersService: UsersService) {}

// Handles HTTP GET requests to '/users'
@Get()
getAllUsers() {
return this.usersService.findAll();
}

// Handles HTTP GET requests to '/users/:id'
@Get(':id')
getUserById(@Param('id') id: string) {
// Converts route parameter to number before passing to service
return this.usersService.findOne(Number(id));
}
}
src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

// Decorator registering controllers and providers for the module
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}

3. Self-Assessment Quiz​

Cargando cuestionario...