First steps
This set of articles covers the core fundamentals of Nest. To introduce the essential building blocks of a Nest application, we'll build a basic CRUD application whose features cover a lot of ground at an introductory level.
Language#
Nest is written in TypeScript and runs on Node.js, and it supports both TypeScript and plain JavaScript. Because Nest relies on the latest language features, using it with plain JavaScript requires Babel.
Most examples in this documentation use TypeScript, but you can switch any code snippet to plain JavaScript syntax with the language toggle in the upper-right corner of the snippet.
Prerequisites#
Make sure that Node.js is installed on your operating system. Running a Nest application requires v20.19 or later (or v22.12+ on the 22.x line). The Nest CLI's generators (such as nest new and nest generate) require v22.22.3+, v24.15+, or v26+. We recommend the latest active LTS release, which satisfies both requirements.
Setup#
The quickest way to set up a new project is with the Nest CLI. With npm installed, run the following commands in your terminal:
$ npm i -g @nestjs/cli
$ nest new project-name
The CLI asks which module system to use: ESM (the default), which uses Vitest as the test runner, or CommonJS, which uses Jest.
It also asks whether to set up NestJS Observe, the official observability platform for Nest. If you answer yes, the generated project includes the @nestjs/observe SDK, already wired into AppModule and NestFactory.create(). Requests, background jobs, errors, and distributed traces start reporting as soon as you supply your app key and secret, and the free plan needs no payment details. In an interactive terminal, the prompt defaults to yes; in non-interactive environments, such as CI, it is skipped and Observe is not added. Pass --observe or --no-observe to skip the prompt either way. See the Observability chapter for what Observe covers.
Hint New projects are generated with TypeScript's strict mode enabled. To opt out, set"strict": falsein the generatedtsconfig.json.
The CLI creates a project-name directory, installs the dependencies, generates a few boilerplate files, and populates a src/ directory with several core files.
The following table describes these core files:
app.controller.ts | A basic controller with a single route. |
app.controller.spec.ts | The unit tests for the controller. |
app.module.ts | The root module of the application. |
app.service.ts | A basic service with a single method. |
main.ts | The entry file of the application. It uses NestFactory to create a Nest application instance. |
The main.ts file contains an async function that bootstraps the application:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module.js';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT ?? 3000);
}
await bootstrap();
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module.js';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT ?? 3000);
}
await bootstrap();
To create a Nest application instance, use NestFactory from @nestjs/core, which exposes a few methods for this purpose. The create() method returns an application object that implements the INestApplication interface. The methods of this object are described in the following chapters. In the main.ts example above, the application starts an HTTP listener and waits for inbound HTTP requests.
The project structure generated by the Nest CLI encourages the convention of keeping each module in its own dedicated directory.
Hint By default, if an error occurs while the application is being created, the process exits with code1. To have the error thrown instead, disable theabortOnErroroption (e.g.,NestFactory.create(AppModule, { abortOnError: false })).
Platform#
Nest is designed to be platform-agnostic. Platform independence lets you create reusable logical parts that can be used across several different types of applications. Nest can work with any Node.js HTTP framework once an adapter is created for it. Two HTTP platforms are supported out of the box: Express and Fastify. Choose the one that best suits your needs.
platform-express | Express is a well-known, minimalist web framework for Node.js. It is a battle-tested, production-ready library with extensive community resources. Nest uses the @nestjs/platform-express package by default, so no setup is required. |
platform-fastify | Fastify is a high-performance, low-overhead framework focused on efficiency and speed. To learn how to use it, see Performance (Fastify). |
Each platform exposes its own application interface: NestExpressApplication and NestFastifyApplication, respectively.
When you pass a type to the NestFactory.create() method, as in the example below, the app object exposes methods that are available only on that platform. You don't need to specify a type unless you want to access the underlying platform API.
const app = await NestFactory.create<NestExpressApplication>(AppModule);
Running the application#
Once the installation is complete, run the following command to start the application and listen for inbound HTTP requests:
$ npm run start
Hint To speed up development builds, use the SWC builder by passing the-b swcflag to thestartscript:npm run start -- -b swc.
This command starts the HTTP server on the port defined in the src/main.ts file (3000, unless the PORT environment variable is set). Once the application is running, open your browser and navigate to http://localhost:3000/. You should see the Hello World! message.
To watch your files for changes, start the application with the following command instead:
$ npm run start:dev
This command watches your files and, whenever they change, recompiles and restarts the server.
Linting and formatting#
The Nest CLI aims to scaffold a reliable development workflow that scales. For a fast default workflow, generated TypeScript projects come with a code linter and a formatter preinstalled: oxlint and Prettier, respectively.
Hint Not sure how formatters and linters differ? See Prettier's comparison.
For headless environments where an IDE is not involved (continuous integration, Git hooks, etc.), the project includes ready-to-use npm scripts that run oxlint and prettier:
# Lint with oxlint
$ npm run lint
# Format with prettier
$ npm run format

