๐ Day 2: Building a Core Feature with NestJSโโโThe User Module
On Day 1, we set up our NestJS project.
๐ Day 2: Building a Core Feature with NestJS โ The User Module

On Day 1, we set up our NestJS project.
Now, on Day 2, weโll learn how to scaffold a core feature (User) using the Nest CLI.
Weโll explore:
- Scaffolding with nest g resource and individual CLI commands
- How module, controller, service, and test files fit together
- Request โ Response flow (with diagram)
- Route mapping, status codes, and error handling
- Running CRUD endpoints with sample requests
- Preparing for database integration (coming next)
โ โ
๐ Table of Contents
- Option 1: Scaffold Full Resource (
nest g resource user) - Option 2: Create Module, Controller, Service Separately
-
[Request โ Response Flow (with Diagram)](#-request โ response-flow-with-diagram)
โ โ
๐น What is Scaffolding in NestJS?
Scaffolding means automatically generating files and boilerplate code using the Nest CLI.
๐ Instead of writing everything from scratch, the CLI creates a module, service, controller, and test files for you.
Example:
nest g resource user
This generates a complete User feature with CRUD endpoints.
โ โ
๐น Creating a User Resource with Nest CLI
- Option 1: Scaffold Full Resource (nest g resource user)
Run:
nest g resource user
Youโll see interactive prompts:
? What transport layer do you use? (Use arrow keys)
> REST API
GraphQL (code first)
GraphQL (schema first)
Microservice
WebSockets
? Would you like to generate CRUD entry points? (Y/n)
๐ Choose:
- REST API
- Yes (to auto-generate CRUD endpoints)
Output (preview of generated files):
CREATE src/user/user.module.ts
CREATE src/user/user.controller.ts
CREATE src/user/user.controller.spec.ts
CREATE src/user/user.service.ts
CREATE src/user/user.service.spec.ts
CREATE src/user/dto/create-user.dto.ts
CREATE src/user/dto/update-user.dto.ts
CREATE src/user/entities/user.entity.ts
โ -
- Option 2: Create Module, Controller, Service Separately
If you donโt want auto-CRUD, you can create them step by step:
nest g module user # Creates user.module.ts
nest g controller user # Creates user.controller.ts + test
nest g service user # Creates user.service.ts + test
๐ For a specific folder:
nest g controller features/user
This would place the controller inside src/features/user/.
๐ก Use โ dry-run to preview changes without actually generating:
nest g service user - dry-run
โ โ
๐ Generated Folder Structure
After running nest g resource user:
src/user/
dto/ # DTOs go here (weโll use them formally in the next lesson)
entities/ # DB models/schemas later
user.controller.ts # Routes + request/response
user.service.ts # Business logic
user.module.ts # Declares the feature
user.controller.spec.ts # Controller unit tests
user.service.spec.ts # Service unit tests
โ โ
๐น Understanding the Files
Module
๐ user.module.ts
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
@Module({
controllers: [UserController], // Registers UserController
providers: [UserService], // Registers UserService
})
export class UserModule {}
- A module groups related controllers & services. UserModule is imported into AppModule so Nest knows about it.
โ โ
Controller:-
๐ user.controller.ts
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Controller('user') // Base route: /user
export class UserController {
constructor(private readonly userService: UserService) {}
@Post() // POST /user
create(@Body() createUserDto: CreateUserDto) {
return this.userService.create(createUserDto);
}
@Get() // GET /user
findAll() {
return this.userService.findAll();
}
@Get(':id') // GET /user/:id
findOne(@Param('id') id: string) {
return this.userService.findOne(+id);
}
@Patch(':id') // PATCH /user/:id
update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
return this.userService.update(+id, updateUserDto);
}
@Delete(':id') // DELETE /user/:id
remove(@Param('id') id: string) {
return this.userService.remove(+id);
}
}
- Handles routes (API endpoints).
- Delegates logic to the service layer.
โ โ
Service
๐ user.service.ts:-
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Injectable() // Makes this service injectable into controllers
export class UserService {
private users = []; // Temporary in-memory storage
create(createUserDto: CreateUserDto) {
const newUser = { id: Date.now(), โฆcreateUserDto };
this.users.push(newUser);
return newUser;
}
findAll() {
return this.users;
}
findOne(id: number) {
return this.users.find((user) => user.id === id);
}
update(id: number, updateUserDto: UpdateUserDto) {
const user = this.findOne(id);
if (!user) return null;
Object.assign(user, updateUserDto);
return user;
}
remove(id: number) {
this.users = this.users.filter((user) => user.id !== id);
return { deleted: true };
}
}
- @Injectable() โ Marks class as a service that can be injected into controllers.
- Business logic lives here.
โ โ
Test Files
๐ user.controller.spec.ts:-
import { Test, TestingModule } from '@nestjs/testing';
import { UserController } from './user.controller';
import { UserService } from './user.service';
describe('UserController', () => {
let controller: UserController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UserController],
providers: [UserService],
}).compile();
controller = module.get<UserController>(UserController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
๐ user.service.spec.ts:-
import { Test, TestingModule } from '@nestjs/testing';
import { UserService } from './user.service';
describe('UserService', () => {
let service: UserService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UserService],
}).compile();
service = module.get<UserService>(UserService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
โ -
๐น Full AppModule Setup
๐ app.module.ts:-
import { Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
@Module({
imports: [UserModule], // Register UserModule here
controllers: [],
providers: [],
})
export class AppModule {}
๐ Why?
- The AppModule is the root module.
- Importing UserModule makes its routes/services available to the whole app.
โ โ
๐น Request โ Response Flow (with Diagram)
โ โ
๐น CRUD Endpoints for User
1. GET All Users
curl http://localhost:3000/user
๐ Returns empty array [] initially.
2. POST Create User
curl -X POST http://localhost:3000/user \
-H "Content-Type: application/json" \
-d '{"name": "Ajay", "email": "ajay@example.com"}'
3. GET One User
curl http://localhost:3000/user/1692817731123
4. PATCH Update User
curl -X PATCH http://localhost:3000/user/1692817731123 \
-H "Content-Type: application/json" \
-d '{"email": "ajay.new@example.com"}'
5. DELETE User
curl -X DELETE http://localhost:3000/user/1692817731123
โ โ
๐น Error Handling in NestJS
Throwing Errors:-
import { NotFoundException } from '@nestjs/common';
findOne(id: number) {
const user = this.users.find((u) => u.id === id);
if (!user) {
throw new NotFoundException(`User with ID ${id} not found`);
}
return user;
}
Custom Error Responses
import { HttpException, HttpStatus } from '@nestjs/common';
update(id: number, dto: UpdateUserDto) {
const user = this.findOne(id);
if (!user) {
throw new HttpException(
{ status: HttpStatus.NOT_FOUND, error: 'User not found' },
HttpStatus.NOT_FOUND,
);
}
Object.assign(user, dto);
return user;
}
โ โ
๐น Next Steps (DB Integration Preview)
In the next tutorial, weโll:
- Add a database (MongoDB or PostgreSQL)
- Use TypeORM/Mongoose
- Implement DTOs, validation pipes, and schemas
- Replace in-memory storage with a persistent DB
โ โ
๋ฉํ๋ฐ์ดํฐ
- post_id
- 82cd2c75624e
- slug
- day-2-building-a-core-feature-with-nestjs-the-user-module-82cd2c75624e
- url
- https://medium.com/@ajaymaurya6798/day-2-building-a-core-feature-with-nestjs-the-user-module-82cd2c75624e
- canonical_url
- https://medium.com/@ajaymaurya6798/day-2-building-a-core-feature-with-nestjs-the-user-module-82cd2c75624e
- author_url
- https://medium.com/@ajaymaurya6798
- status
- ok
- fetched_at
- 2026-08-24 15:44:55