Skip to content

How a NestJS App Hatches — Explained Like You're a Sleep-Deprived Dev

So you've chosen NestJS — the TypeScript back-end framework that looks like Angular and feels like Express got a spa day. But how does it actually work under the hood?

Let’s walk through the life of a request in NestJS — from birth (main.ts) to glory (Controller/Service) — with a healthy dash of humor.

🎬 Scene 1: The App is Born — main.ts

This is where everything begins. This file is like Iron Man shouting “I AM… the app entry point!”

ts
// src/main.ts
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";

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

  app.setGlobalPrefix("api"); // So all routes start with /api

  await app.listen(3000);
}
bootstrap();

💡 TL;DR

  • main.ts boots your app.
  • Want all APIs to start with /api? Do it here.
  • Want to add global guards, pipes, or CORS? Yup — here.

🧱 Scene 2: The Blueprint — AppModule

The AppModule is the real MVP. Think of it as the city planner — it decides what modules get in the city and which ones stay out.

ts
// src/app.module.ts
@Module({
  imports: [UsersModule, AuthModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

🔥 Quick Recap

  • You define feature modules here.
  • Import anything you need globally.
  • If main.ts is Iron Man, AppModule is the Avengers HQ.

🛣️ Scene 3: Roads & Routes — Controller

Now it’s time for roads (aka routes) to be built. Say hello to @Controller.

ts
@Controller("users") // Base route: /users
export class UsersController {
  @Get() // GET /users
  findAll() {
    return this.userService.findAll();
  }

  @Get(":id") // GET /users/123
  findOne(@Param("id") id: string) {
    return this.userService.findOne(id);
  }
}

🛑 Pro Tip: You can use decorators like @Post(), @Put(), @Delete() just like toppings on your pizza.

🧙‍♂️ Scene 4: The Real Brains — Service

Services are the Gandalf of NestJS. They do the real work: talking to databases, processing data, or telling other services what to do.

ts
@Injectable()
export class UsersService {
  findAll() {
    return [{ name: "Kahnu" }];
  }

  findOne(id: string) {
    return { id, name: "Kahnu" };
  }
}

🛡️ Scene 5: Guards, Interceptors & Pipes — The Bouncers 🕴️

When you hit a controller, there might be guards at the door checking ID (auth), interceptors fixing your hair (modifying responses), and pipes ensuring you're clean (validation).

ts
@UseGuards(JwtAuthGuard)
@Get('profile')
getProfile(@Request() req) {
  return req.user;
}

🧵 Scene 6: A Request's Life Journey

Let’s follow a request like it’s Simba running through the Pride Lands:

Client ➝ main.ts ➝ AppModule ➝ Controller ➝ Guard ➝ Pipe ➝ Interceptor ➝ Service ➝ Response
plaintext
    +-------------+
    |  main.ts    | 🧠 Boots the app
    +-------------+

    +-------------+
    | AppModule   | 🧩 Imports modules
    +-------------+

    +-------------+
    | Controller  | 🚦 Handles routes
    +-------------+

    +-------------+
    |   Guard     | 🛡️ Checks auth
    +-------------+

    +-------------+
    |   Pipe      | 🚿 Validates/cleans input
    +-------------+

    +-------------+
    | Interceptor | 💄 Enhances response
    +-------------+

    +-------------+
    |  Service    | 🔧 Does business logic
    +-------------+

       🎉 Response

🔧 Where to Put Bootstrap-Level Config

In main.ts:

ts
app.setGlobalPrefix("api"); // Prefixes all routes with /api
app.enableCors(); // CORS for frontend love
app.useGlobalPipes(new ValidationPipe()); // DTO validation

🤔 Do I Always Need a Service?

Nope. For a simple “Hello World” endpoint, a controller alone works:

ts
@Controller()
export class AppController {
  @Get()
  hello() {
    return "Hello from NestJS!";
  }
}

But for anything more than that? Use a service — it keeps things clean and testable.

🔥 Final Pro Tips

  • Use DTOs (*.dto.ts) to validate incoming data.
  • Use Guards (JwtAuthGuard, RolesGuard) to control access.
  • Use Modules to break up features like LEGO blocks.
  • Your app starts in main.ts, lives in modules, and shines through controllers.

Built by noobs, for noobs, with love 💻❤️