Lesson 41 of 49 intermediate

NestJS Setup & First App

From Zero to Running Server in 5 Minutes

Open interactive version (quiz + challenge)

Real-world analogy

Installing NestJS is like moving into a fully furnished apartment. The CLI hands you the keys, and inside you find rooms already labeled (modules), a reception desk (controller), a workshop (service), and utilities hooked up (config). You don't hunt for furniture — just unpack your ideas and start living!

What is it?

Setting up NestJS involves installing the CLI, scaffolding a project, understanding the file structure, and running the development server. The CLI automates project creation and code generation so you can focus on building features, not configuring tools.

Real-world relevance

Every NestJS project at companies like Adidas, Roche, and thousands of startups starts exactly this way — `nest new`, then `nest g resource`. The CLI ensures every team member starts with the same clean structure.

Key points

Code example

// Step 1: Install NestJS CLI globally
// npm i -g @nestjs/cli

// Step 2: Create a new project
// nest new my-awesome-api

// Step 3: Look at the project structure
// my-awesome-api/
//   src/
//     main.ts          ← Entry point
//     app.module.ts    ← Root module
//     app.controller.ts ← Route handler
//     app.service.ts   ← Business logic
//   test/
//     app.e2e-spec.ts  ← E2E tests
//   package.json
//   tsconfig.json
//   nest-cli.json      ← CLI config

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

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

  // Enable CORS for frontend access
  app.enableCors();

  // Set a global prefix: /api/users, /api/products
  app.setGlobalPrefix('api');

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

// src/app.module.ts — The root module
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],           // Other modules go here
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

// src/app.controller.ts — Handle requests
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('health')
  healthCheck() {
    return { status: 'ok', timestamp: new Date() };
  }
}

// src/app.service.ts — Business logic
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

Line-by-line walkthrough

  1. 1. Step 1: Install NestJS CLI globally
  2. 2. Run this in your terminal
  3. 3.
  4. 4. Step 2: Create a new project
  5. 5. This scaffolds the entire project
  6. 6.
  7. 7. Step 3: Look at the project structure
  8. 8. The project folder
  9. 9. Source code folder
  10. 10. Entry point — starts the server
  11. 11. Root module — organizes everything
  12. 12. Route handler — handles HTTP requests
  13. 13. Business logic — does the actual work
  14. 14. Test folder
  15. 15. End-to-end test file
  16. 16. Package dependencies
  17. 17. TypeScript configuration
  18. 18. NestJS CLI configuration
  19. 19.
  20. 20. src/main.ts — The ignition key
  21. 21. Importing NestFactory to create the app
  22. 22. Importing the root module
  23. 23.
  24. 24. Defining the bootstrap function
  25. 25. Creating the NestJS app from AppModule
  26. 26.
  27. 27. Enable CORS for frontend access
  28. 28. Allow cross-origin requests
  29. 29.
  30. 30. Set a global prefix for all routes
  31. 31. All routes will start with /api
  32. 32.
  33. 33. Start listening on port 3000
  34. 34. Log a success message
  35. 35. Closing the bootstrap function
  36. 36. Call the bootstrap function to start
  37. 37.
  38. 38. src/app.module.ts — The root module
  39. 39. Importing the Module decorator
  40. 40. Importing the controller
  41. 41. Importing the service
  42. 42.
  43. 43. Module decorator with configuration
  44. 44. Import other modules here
  45. 45. Controllers handle HTTP routes
  46. 46. Services provide business logic
  47. 47. Closing the decorator
  48. 48. Exporting the AppModule class
  49. 49.
  50. 50. src/app.controller.ts — Handle requests
  51. 51. Importing decorators from NestJS
  52. 52. Importing the service
  53. 53.
  54. 54. Controller decorator — base route
  55. 55. Exporting the controller class
  56. 56. Injecting the service via constructor
  57. 57.
  58. 58. GET / — returns hello message
  59. 59. Calling the service method
  60. 60. Return type is string
  61. 61. Closing the method
  62. 62.
  63. 63. GET /health — health check endpoint
  64. 64. Returning status and timestamp
  65. 65. Closing the method
  66. 66. Closing the controller
  67. 67.
  68. 68. src/app.service.ts — Business logic
  69. 69. Importing Injectable decorator
  70. 70.
  71. 71. Injectable marks this as a provider
  72. 72. Exporting the service class
  73. 73. A simple method that returns a string
  74. 74. Returning the hello message
  75. 75. Closing the method
  76. 76. Closing the class

Spot the bug

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

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.listen(3000);
}
bootstrap();
Need a hint?
What's missing before app.listen()? Check the original main.ts for comparison...
Show answer
app.listen(3000) is missing the 'await' keyword. Without await, the server might not fully start before the function ends. Fix: await app.listen(3000). Also, there's no console.log to confirm the server started — add one after listen!

Explain like I'm 5

Imagine you want to build a treehouse. You could start from scratch — finding wood, nails, a hammer. Or you could get a treehouse KIT with pre-cut pieces and instructions. NestJS CLI is that kit. You type one command and BOOM — your treehouse (server) is ready. You just need to decorate it (add your features)!

Fun fact

The NestJS CLI generates over 15 types of files: modules, controllers, services, guards, pipes, interceptors, filters, decorators, gateways, middlewares, interfaces, classes, enums, libraries, and sub-apps. It's like a code factory!

Hands-on challenge

Install the NestJS CLI, create a new project with `nest new my-first-api`, run it with `npm run start:dev`, then visit http://localhost:3000. Next, add a `/health` endpoint that returns `{ status: 'ok', uptime: process.uptime() }`. Bonus: generate a cats resource with `nest g resource cats` and explore the files it creates!

More resources

Open interactive version (quiz + challenge) ← Back to course: Full-Stack Playbook