nest_01_intro - Installation & First App¶
Table of Contents¶
- installing the CLI
- project structure breakdown
- the main.ts boilerplate
- decorators are everywhere
- running the app
- what's actually happening
- common first-timer mistakes
- prerequisites
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()
flowchart TD
subgraph Request["HTTP Request Flow"]
Req["Incoming Request"] --> Guard["Guard
@UseGuards(AuthGuard)
authorization check"]
Guard -->|allowed| Pipe["Pipe
@UsePipes(ValidationPipe)
transform + validate"]
Pipe -->|valid| Interceptor["Interceptor
@UseInterceptors(LogInterceptor)
pre-processing"]
Interceptor --> Controller["Controller
@Controller('users')
route handling"]
Controller --> Service["Service / Provider
@Injectable()
business logic"]
Service --> DB["Database / External API"]
DB --> Service --> Controller
Controller --> Interceptor2["Interceptor
post-processing"]
Interceptor2 --> Response["HTTP Response"]
Guard -->|denied| Forbidden["401 / 403 Forbidden"]
Pipe -->|invalid| BadReq["400 Bad Request"]
end
subgraph Modules["Module Organization"]
M1["UsersModule
imports: []
controllers: [UsersController]
providers: [UsersService]"]
M2["AuthModule
imports: [JwtModule]
controllers: [AuthController]
providers: [AuthService]"]
Root["AppModule
imports: [UsersModule, AuthModule]"]
end
Root --> M1
Root --> M2
style Req fill:#3498db,color:#fff
style Guard fill:#e74c3c,color:#fff
style Pipe fill:#f1c40f,color:#000
style Interceptor fill:#9b59b6,color:#fff
style Controller fill:#2ecc71,color:#fff
style Service fill:#1abc9c,color:#fff
style Response fill:#3498db,color:#fff
style Root fill:#e67e22,color:#fff
style M1 fill:#95a5a6,color:#fff
style M2 fill:#95a5a6,color:#fff 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):
- Nest reads the
@Moduledecorator metadata from AppModule - It walks imports , controllers , and providers recursively
- It builds the dependency injection container with all providers
- It registers all controllers with the underlying Express instance
- It applies global pipes , guards , interceptors , and filters
- 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/commonand@nestjs/coreare different packages - common has the decorators , core has the runtime - Running the app without
start:devand wondering why changes don't auto-reload - that's what:devsuffix does - Importing
expresstypes thinking you need them - Nest has its own request/response types that wrap Express
prerequisites¶
nest_00_home - NestJS HOME