How to Set Up Your First NestJS Project

How to Set Up Your First NestJS Project

So, you have heard that NestJS is clean, structured, scalable, and probably a better long-term choice than letting your backend turn into a folder full of “final-final-real-final.js”.

Nice.

Now it is time to actually build your first project.

In this guide, we will go step by step and keep it beginner-friendly.
No weird shortcuts.
No assuming you already know the entire Node.js ecosystem by heart.

By the end, you will have:
- Node.js installed
- Nest CLI installed
- your first NestJS project created
- the app running locally
- a clear understanding of what the generated project structure is doing

Let’s get into it.

What you need before you start

Before creating a NestJS project, you need a few basics installed on your machine:

- **Node.js**
- **npm** (comes with Node.js)
- **A code editor**, like VS Code
- **A terminal**

For production-style development, Node recommends using an LTS release rather than a short-lived current release, and as of early April 2026 Node 24 is the latest LTS line.

If you already have Node installed, you can check your version with:

node -v
npm -v

If those commands work, great.
You are already in decent shape.

If not, install Node.js first, then come back with confidence and a slightly stronger terminal presence.

Step 1: Install the Nest CLI

The easiest way to create a NestJS app is with the Nest CLI.

Install it globally with:

npm i -g @nestjs/cli

This is still the standard setup command in the current Nest “First steps” guide.

Why use the CLI?

Because it saves you from doing boring setup manually.
It creates the starter project, adds the core files, and gives you useful generators later for things like modules, controllers, and services. Nest’s CLI command reference documents nest new, nest start, and nest generate for these workflows.

You can verify the CLI is installed with:

nest --version

Step 2: Create Your First NestJS Project

Now create a new project:

nest new my-first-nest-app

Nest will ask you to choose a package manager, usually:

  • npm
  • yarn
  • pnpm

Pick the one you are comfortable with.

Once you confirm, the CLI will:

  • create a new folder
  • install dependencies
  • generate starter files
  • prepare a working NestJS app

That is exactly what the current CLI docs describe for nest new: it creates the folder, adds config files, builds /src and /test, and initializes starter app files.

If you want a stricter TypeScript setup from day one, Nest also supports:

nest new my-first-nest-app --strict

The official docs note that --strict enables a stricter TypeScript compiler setup.

For beginners, using --strict is actually a pretty good habit.
It may complain more, but that is often TypeScript doing you a favor before production does the complaining for you.

Step 3: Move Into the Project Folder

Once the project is created:

cd my-first-nest-app

Now you are inside your NestJS app.

This is the moment where everything feels new, slightly suspicious, and kind of exciting.

Step 4: Run the App

Start the project with:

npm run start

Or during development, use watch mode:

npm run start:dev

From the CLI side, Nest also supports:

nest start
nest start --watch

The official CLI reference still lists nest start and --watch as the standard way to compile and run the app in watch mode.

Once the app starts, open:

http://localhost:3000

You should see the default response:

Hello World!

That comes from the starter controller and service that Nest generates for you.

If you see that message, congratulations.
Your first NestJS app is alive.

Step 5: Understand the Starter Project Structure

Now let’s look at the files Nest generated.

A new Nest project includes a src/ directory with these starter files:

  • app.controller.ts
  • app.controller.spec.ts
  • app.module.ts
  • app.service.ts
  • main.ts

Here is what they mean in normal human language.

main.ts

This is the entry point of your application.

It bootstraps the app using NestFactory and starts the HTTP server. The official starter code calls NestFactory.create(AppModule) and then app.listen(process.env.PORT ?? 3000).

Typical starter version:

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

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(process.env.PORT ?? 3000);
}
bootstrap();

This file is basically saying:

“Hey Nest, take my root module, build the application, and start listening for requests.”

Simple. Important. Respect it.

app.module.ts

This is the root module.

Nest uses modules to organize your application.
At the beginning, AppModule is the top-level container that wires the basic parts together.

Think of it like the main room where the first pieces of your backend get registered.


app.controller.ts

This file handles incoming requests.

In the starter project, it usually contains a very simple route for / that returns the default response.

It is your first example of a controller in action.


app.service.ts

This file contains the business logic used by the controller.

In the starter app, it usually just returns the "Hello World!" string.

This separation is small now, but it teaches a very important Nest habit:

  • controllers handle requests
  • services handle logic

That habit becomes super useful when your app grows.


app.controller.spec.ts

This is a test file.

Even if you are not focused on testing yet, it is nice that Nest gives you a testing example immediately.

It is basically Nest saying:
“You may ignore this today, but your future self will be glad this exists.”


Step 6: Make Your First Tiny Change

Let’s do a small edit so the project feels like yours.

Open app.service.ts and change the returned text.

For example:

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Welcome to my first NestJS project!';
  }
}

Save the file.

If you are using watch mode, the app should reload automatically. The CLI docs still list watch mode for nest start --watch, and Nest’s standard starter scripts provide the same live development workflow.

Refresh http://localhost:3000

Now you should see your new message.

This is a tiny step, but it matters because it confirms:

  • your app is running
  • your code changes are applied
  • the project is not just a template anymore

Now it is yours.


Step 7: Generate New Files with the CLI

One of the best parts of NestJS is that the CLI can generate common building blocks for you.

For example, you can create a module:

nest g module users

A controller:

nest g controller users

And a service:

nest g service users

The current CLI command reference still includes generators for module, controller, service, plus many others such as guard, pipe, interceptor, and resource.

This is one of those things that feels small at first, but later saves a lot of repetitive work.

Also, it helps keep your project structure consistent, which is one of the biggest reasons people enjoy working with Nest.


Step 8: Know the Difference Between src/, dist/, and test/

As your project grows, these folders matter.

src/

This is where your actual application source code lives.

You will spend most of your time here.

dist/

This is the compiled output folder after building the app.

You usually do not edit files here manually.

test/

This is where end-to-end or other test-related files can live, depending on your setup.

The Nest CLI docs explicitly note that nest new creates source code under /src and end-to-end tests under /test.

So the mental model is:

  • write code in src
  • generated build output goes to dist
  • testing files live in test

Easy enough.


Step 9: Add Environment Variables the Right Way

Sooner or later, you will want config values like:

  • port
  • database URL
  • API keys
  • environment mode

Nest’s current configuration docs recommend using .env files together with @nestjs/config, typically imported via ConfigModule.forRoot() in the root module.

Install it like this:

npm i --save @nestjs/config

Then in app.module.ts:

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [ConfigModule.forRoot()],
})
export class AppModule {}

By default, ConfigModule.forRoot() loads a .env file from the project root and merges it with runtime environment variables; if the same key exists in both places, the runtime environment value takes precedence.

Example .env file:

PORT=3000
APP_NAME=my-first-nest-app

This is not something you must fully master on day one.
But it is a good habit to know early.

Because “I hardcoded it for now” has a way of surviving much longer than it should.


Common Beginner Mistakes During Setup

Let’s save you from a few classic first-day problems.

1. Node version issues

If Nest or dependencies behave strangely, check your Node version first. Using an LTS version is the safest choice for real projects.

2. CLI not recognized

If nest is not found, the global CLI install may not have worked, or your npm global bin path is not available in your shell.

3. Wrong folder

This happens more than people admit.

You create the app, but run commands outside the project folder.

Then everything feels broken, but really the terminal is just in the wrong place.

A classic.

4. Port already in use

If port 3000 is busy, your app may fail to start. The starter bootstrap uses process.env.PORT ?? 3000, so setting PORT is the simplest way to switch.

5. Editing dist/ instead of src/

Never trust tired-you around compiled folders.

Write your code in src.

Always.


Why This Setup Step Actually Matters

It is easy to think setup is just the boring part you rush through before “real coding.”

But in NestJS, the starter project teaches you a lot right away:

  • apps are organized around modules
  • controllers and services are separated
  • the app starts from a single bootstrap file
  • the CLI is part of the normal workflow
  • structure matters from day one

That is a big reason Nest feels different from loosely organized Node projects.

It nudges you toward clean architecture early.

And honestly, that is one of its best qualities.


Final Thoughts

Setting up your first NestJS project is not hard.

The main flow is really just:

  1. install Node.js
  2. install the Nest CLI
  3. create a project
  4. run it
  5. understand the generated structure
  6. make a tiny change
  7. start building

That is it.

Once you have done this once, Nest starts to feel much less intimidating.

And from here, the next step is the really important one:

understanding modules, controllers, and providers

Because that is where NestJS starts to truly make sense.

Now that your first NestJS project is running, the next question is the one that really matters:

What are all these files actually doing?

In the next article, we’ll break down the three core building blocks of a NestJS app — modules, controllers, and providers — so you can understand how everything fits together instead of just running code and hoping for the best.


FAQ

Do I need TypeScript to start a NestJS project?

No. Nest supports JavaScript too, and the CLI can generate a project with --language JS. But most Nest projects use TypeScript, and that is the default developer path.

What command creates a new NestJS app?

Use:

nest new my-first-nest-app

That is the standard project creation command in the official CLI docs.

What file starts the NestJS application?

main.ts is the entry file that bootstraps the app with NestFactory.

What port does NestJS use by default?

The default starter app listens on process.env.PORT ?? 3000, so it uses port 3000 unless PORT is set.

Should I learn the Nest CLI early?

Yes. It saves time, keeps your structure consistent, and is part of the normal Nest development workflow. The official CLI supports project creation, generators, builds, and watch-mode startup.

Subscribe for new post. No spam, just tech.