Skip to content
Back to skills

Nestjs Controller Pattern

ASecurity

> Define HTTP route handlers with @Controller, method decorators, params, and versioning

  • 20 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 11, 2026
businesstypescriptexpressapi

Works with

  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 11, 2026

npx -y skills add Intense-Visions/harness-engineering --skill nestjs-controller-pattern --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Nestjs Controller Pattern?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Nestjs Controller Pattern
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/intense-visions-nestjs-controller-pattern/badge)](https://www.skillsdirectory.com/skills/intense-visions-nestjs-controller-pattern)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# NestJS Controller Pattern

> Define HTTP route handlers with @Controller, method decorators, params, and versioning

## When to Use

- You are creating a new REST endpoint or modifying an existing route
- You need to extract path params, query strings, or request body from incoming requests
- You want to add API versioning to your routes
- You need to bypass NestJS response handling and write directly to the underlying response object

## Instructions

1. Decorate the class with `@Controller('resource')` to set the route prefix. Use kebab-case for multi-word resources (`@Controller('user-profiles')`).
2. Use method decorators `@Get()`, `@Post()`, `@Put()`, `@Patch()`, `@Delete()` to bind HTTP methods. Nest the path in the decorator when appropriate: `@Get(':id')`.
3. Extract route data with parameter decorators:
   - `@Param('id')` — path parameter
   - `@Query('page')` — query string parameter
   - `@Body()` — full request body (use a DTO class for type safety)
   - `@Headers('authorization')` — request header
   - `@Req()` / `@Res()` — raw Express/Fastify request/response (avoid unless necessary)
4. Return values from handlers are automatically serialized to JSON. Do NOT inject `@Res()` unless you need to stream or set custom headers — doing so bypasses NestJS interceptors and exception filters.
5. Apply `@HttpCode(201)` to `@Post()` handlers that create resources (default is 200).
6. Use `@Header('Cache-Control', 'no-cache')` for static header overrides.

```typescript
@Controller({ path: 'articles', version: '1' })
export class ArticlesController {
  constructor(private readonly articlesService: ArticlesService) {}

  @Get()
  findAll(@Query('page') page = 1, @Query('limit') limit = 20) {
    return this.articlesService.findAll({ page, limit });
  }

  @Get(':id')
  findOne(@Param('id', ParseUUIDPipe) id: string) {
    return this.articlesService.findOne(id);
  }

  @Post()
  @HttpCode(201)
  create(@Body() createArticleDto: CreateArticleDto) {
    return this.articlesService.create(createArticleDto);
  }

  @Patch(':id')
  update(@Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateArticleDto) {
    return this.articlesService.update(id, dto);
  }

  @Delete(':id')
  @HttpCode(204)
  remove(@Param('id', ParseUUIDPipe) id: string) {
    return this.articlesService.remove(id);
  }
}
```

7. Enable versioning app-wide in `main.ts`: `app.enableVersioning({ type: VersioningType.URI })`. Then use `@Controller({ version: '1' })` or `@Version('2')` on individual handlers.
8. Keep controllers thin — they orchestrate, they do not contain business logic. All logic lives in the service layer.

## Details

Controllers are the entry point for HTTP requests in NestJS. They are registered in the `controllers` array of their parent module and are not injectable themselves.

**Route ordering:** NestJS registers routes in declaration order. Static routes (`/articles/trending`) must be declared before dynamic routes (`/articles/:id`) within the same controller to avoid shadowing.

**@Res() caution:** When you inject `@Res()`, NestJS hands off response management entirely to you. Interceptors (including serialization and transformation interceptors) will NOT run. If you only need to set headers or status codes, use `@HttpCode()` and `@Header()` decorators instead. If you must use `@Res()`, pass `{ passthrough: true }` to keep NestJS in control: `@Res({ passthrough: true })`.

**Pipe integration:** Built-in pipes like `ParseIntPipe`, `ParseUUIDPipe`, `ParseBoolPipe` can be passed directly in the parameter decorator: `@Param('id', ParseUUIDPipe) id: string`. The pipe validates and transforms before the handler executes.

**Versioning strategies:** URI (`/v1/articles`), Header (`X-API-Version: 1`), Media Type (`Accept: application/vnd.api+json;v=1`), and Custom are all supported. URI versioning is the most visible and cacheable.

## Source

https://docs.nestjs.com/controllers

## Process

1. Read the instructions and examples in this document.
2. Apply the patterns to your implementation, adapting to your specific context.
3. Verify your implementation against the details and edge cases listed above.

## Harness Integration

- **Type:** knowledge — this skill is a reference document, not a procedural workflow.
- **No tools or state** — consumed as context by other skills and agents.

## Success Criteria

- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.

Files in this skill

  • SKILL.md4.4 KB
  • skill.yaml805 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…