A progressive and production-ready NestJS scaffold template designed for scalability, type-safety, and clean architecture. This project serves as a foundation for building robust e-commerce or catalog-based backends.
- Framework: NestJS v11 (Express-based)
- Language: TypeScript (ES2023)
- Database: PostgreSQL with TypeORM
- Validation: Zod via
nestjs-zodfor absolute type safety. - Authentication: JWT (Passport.js strategy) with Access & Refresh token rotation.
- File Storage: AWS S3 / MinIO integration via AWS SDK v3.
- API Documentation: Integrated Swagger UI (OpenAPI 3.0).
- Tooling: ESLint, Prettier, Jest.
The application is organized into domain-driven modules located in src/modules. Each module is self-contained, encapsulating its own controllers, services, entities, and DTOs.
AuthModule: Identity and access management.UsersModule: Profile and user management.ProductsModule: Catalog and inventory management.CategoriesModule: Hierarchical classification.
To avoid deep relative imports (../../../../), the project uses TypeScript path aliases defined in tsconfig.json:
@modules/*->src/modules/*@common/*->src/common/*@config/*->src/config/*@database/*->src/database/*@helpers/*->src/helpers/*
The backend enforces a strict design system for API communication:
- Success Interceptor: All successful responses are automatically wrapped in a standard
ApiResponsestructure:{ "success": true, "message": "Success", "data": { ... }, "meta": { ... } // Optional (e.g., pagination) } - Global Exception Filter: Errors are caught and formatted consistently by the
HttpExceptionFilter, ensuring even internal errors return a safe and readable JSON response.
We use zod for all DTOs. This ensures that validation and TypeScript types are always in sync. Use the ZodValidationPipe (global) to handle input validation automatically.
- Node.js (v18+)
- PostgreSQL
- S3 Compatible Storage (MinIO or AWS S3)
npm installCopy .env.example to .env and fill in your credentials:
cp .env.example .env# Development
npm run start:dev
# Production Build
npm run build
npm run start:prodOnce the app is running, visit:
- Swagger UI:
http://localhost:3000/docs - Static Spec:
src/swagger.json
When building new features on top of this scaffold, follow these guidelines to maintain consistency:
Use the NestJS CLI or create a directory in src/modules/[feature]:
- Define Entity: Create
entities/[feature].entity.tsusing TypeORM decorators. - Define Schema/DTO: Create
dto/[feature].dto.tsusingzodschemas. - Service: Implement business logic in
[feature].service.ts. - Controller: Define endpoints in
[feature].controller.ts. - Module: Wire everything in
[feature].module.tsand import it intoAppModule.
You do not need to wrap your data in success or message keys manually in the controller. Return the raw data (or a promise), and the ResponseInterceptor will handle the wrapping.
- Custom Message: If you need a specific message, return an object like
{ data, message: 'Your message' }.
Use the S3Helper from @helpers/s3.helper:
constructor(private readonly s3Helper: S3Helper) {}
async upload(file: Express.Multer.File) {
return await this.s3Helper.uploadFile(file, 'folder-name');
}Protect routes using the built-in guards:
- JWT Protection:
@UseGuards(JwtAuthGuard) - Role Based Access:
@Roles(Role.Admin)+@UseGuards(JwtAuthGuard, RolesGuard)
- Always use
uuidfor primary keys. - Use
CreateDateColumnandUpdateDateColumnfor auditing. - Prefer relations over manual ID handling where possible.
- Naming: camelCase for variables/functions, PascalCase for classes, kebab-case for files.
- Comments: We follow the NO non-essential comments rule. Code should be self-documenting. Use comments only for complex algorithmic logic.
- Git: Commits should be descriptive. Feature branches are preferred.