Skip to content

nest_01_intro - Installation & First App

TypeScript is non-negotiable here If you're still writing raw JavaScript in 2026 , close this tab and go take a long look at your life choices NestJS is built on decorators , interfaces , and type metadata - all TypeScript features - and fighting the framework by using JS means you're missing the entire point

what's in here

  • Installing NestJS CLI (@nestjs/cli)
  • Scaffolding your first project
  • The generated project structure explained
  • Understanding decorators (the magic that holds Nest together)
  • Running the app and seeing it work

installing the CLI

Global install or use npx , doesn't matter

npm install -g @nestjs/cli
# or
npx @nestjs/cli new my-first-api

The CLI asks about package manager Pick npm unless you have strong opinions about yarn vs pnpm ( and you probably shouldn't yet ) It generates a full project structure with TypeScript config , test setup , and a working "Hello World" endpoint

project structure breakdown

my-first-api/
  src/
    main.ts              # entry point , bootstraps the app
    app.module.ts        # root module , imports everything
    app.controller.ts    # root controller , handles /
    app.service.ts       # root service , business logic
    app.controller.spec.ts # unit test for the controller
  test/
    app.e2e-spec.ts      # end-to-end test
  nest-cli.json          # NestJS CLI configuration
  tsconfig.json          # TypeScript config (strict mode enabled)
  tsconfig.build.json    # build-specific TS config
  package.json

This looks like ceremony until your app has 40 files and you can still find anything in under 5 seconds The structure is predictable , and predictable is secure because you audit the right places

the main.ts boilerplate

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

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

  // security headers right at bootstrap
  // you'll learn about helmet in the security section
  // app.use(helmet())

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

bootstrap()

NestFactory.create() does a lot under the hood It creates an Express instance (default) , wires up DI , registers pipes/guards/interceptors from global declarations , and returns a configured NestApplication ready to accept connections

The AppModule parameter tells Nest which module is the root Everything else is discovered through imports - Nest traverses the module graph at bootstrap

decorators are everywhere

NestJS uses decorators for basically everything If you've never seen @ syntax before , it looks weird but it's just functions that modify the behavior of the class or method below them

import { Controller, Get } from '@nestjs/common'

@Controller('users')
export class UsersController {
  @Get()
  findAll(): string {
    return 'this endpoint exists'
  }
}

@Controller('users') tells Nest: "this class handles routes under /users" @Get() tells Nest: "this method handles GET /users"

No manual route registration , no express.Router() , no app.get() scattered through bootstrap The decorators declare intent , and Nest wires it up during module initialization

running the app

npm run start:dev

This starts the app with file watching (ts-node under the hood) Change a file , Nest recompiles and restarts For production you'll use npm run build then node dist/main.js , but for development this is fine

Hit http://localhost:3000 and you should see "Hello World!" or whatever the generated controller returns

what's actually happening

When you call NestFactory.create(AppModule):

  1. Nest reads the @Module decorator metadata from AppModule
  2. It walks imports , controllers , and providers recursively
  3. It builds the dependency injection container with all providers
  4. It registers all controllers with the underlying Express instance
  5. It applies global pipes , guards , interceptors , and filters
  6. It starts the HTTP server on the specified port

This all happens in under a second for small apps Larger apps with many modules take a bit more but usually under 3 seconds

common first-timer mistakes

  • Forgetting to register a provider in the module - you'll get a Nest can't resolve dependencies error , and the fix is adding it to providers: [] in the module
  • Not understanding that @nestjs/common and @nestjs/core are different packages - common has the decorators , core has the runtime
  • Running the app without start:dev and wondering why changes don't auto-reload - that's what :dev suffix does
  • Importing express types thinking you need them - Nest has its own request/response types that wrap Express

prerequisites

nest_00_home - NestJS HOME


next -> nest_02_get_started - App Bootstrap & CLI Deep Dive