Quick start
1. Define a DTO and a controller
src/features/hello/dto.ts
import {IsInt, IsString, Min} from "class-validator";
export class CreateHelloDto {
@IsString()
name!: string;
@IsInt()
@Min(0)
age!: number;
}
src/features/hello/controller.ts
import {Controller, Get, Post, Body, type RouteContext} from "nextjs-nestapi";
import {CreateHelloDto} from "./dto";
@Controller("/hello")
export class HelloController {
@Get("")
list() {
return {message: "hello world"};
}
@Get("/:id")
getOne(context: RouteContext) {
return {id: context.params.id};
}
@Post("")
create(@Body(CreateHelloDto) dto: CreateHelloDto) {
return {created: dto};
}
}
2. Register the controller
src/app.ts
import {createApplication} from "nextjs-nestapi";
import {HelloController} from "./features/hello/controller";
export const app = createApplication({
controllers: [HelloController],
basePath: "/api", // default
});
3. Mount it behind a single catch-all route
src/app/api/[[...route]]/route.ts
import {NextRequest} from "next/server";
import {app} from "@/app";
async function handleRequest(request: NextRequest) {
return app.handle(request);
}
export const GET = handleRequest;
export const POST = handleRequest;
export const PUT = handleRequest;
export const PATCH = handleRequest;
export const DELETE = handleRequest;
export const OPTIONS = handleRequest;
export const HEAD = handleRequest;
@Controller("/hello") + @Get("/:id") resolves against ${basePath}/hello/:id — here,
GET /api/hello/:id.
tip
Steps 2–3 are exactly what npx nextjs-nestapi init generates for you.
Next steps
- Controllers & routing — the full decorator surface
- DTO validation — validation error shape and file uploads
- OpenAPI / Swagger docs — auto-generate API documentation