{"id":43462774,"url":"https://github.com/BrahimAbdelli/nestier","last_synced_at":"2026-02-14T10:01:02.137Z","repository":{"id":190892079,"uuid":"614096497","full_name":"BrahimAbdelli/nestier","owner":"BrahimAbdelli","description":"A NestJS Boilerplate to help you build your backend using Typescript Generics, MongoDB, TypeORM, Swagger, Compodoc, MailJet, Docker, Prometheus, Grafana.","archived":false,"fork":false,"pushed_at":"2026-01-24T13:14:01.000Z","size":525,"stargazers_count":50,"open_issues_count":0,"forks_count":14,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-24T22:17:34.260Z","etag":null,"topics":["clean-architecture","ddd","docker","e2e","generic","hexagonal-architecture","jwt","mail","mock","mongodb","nestjs","nodejs","prettier","production-ready","repository-pattern","swagger","typeorm","typescript"],"latest_commit_sha":null,"homepage":"https://www.brahimabdelli.dev/nestjs-boilerplate","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BrahimAbdelli.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-14T22:10:18.000Z","updated_at":"2026-01-24T16:39:17.000Z","dependencies_parsed_at":"2023-08-26T23:27:56.967Z","dependency_job_id":"73485b7b-7277-4ec2-910f-03ebb1fc8085","html_url":"https://github.com/BrahimAbdelli/nestier","commit_stats":null,"previous_names":["brahimabdelli/nestjs-boilerplate","brahimabdelli/nestier"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/BrahimAbdelli/nestier","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrahimAbdelli%2Fnestier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrahimAbdelli%2Fnestier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrahimAbdelli%2Fnestier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrahimAbdelli%2Fnestier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BrahimAbdelli","download_url":"https://codeload.github.com/BrahimAbdelli/nestier/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BrahimAbdelli%2Fnestier/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29442326,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T07:24:13.446Z","status":"ssl_error","status_checked_at":"2026-02-14T07:23:58.969Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clean-architecture","ddd","docker","e2e","generic","hexagonal-architecture","jwt","mail","mock","mongodb","nestjs","nodejs","prettier","production-ready","repository-pattern","swagger","typeorm","typescript"],"created_at":"2026-02-03T06:00:36.879Z","updated_at":"2026-02-14T10:01:02.129Z","avatar_url":"https://github.com/BrahimAbdelli.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://nestjs.com/img/logo-small.svg\" width=\"120\" alt=\"Nest Logo\" /\u003e\n  \u003ch1\u003eNestier\u003c/h1\u003e\n  \u003cp\u003e\n    \u003cstrong\u003eA production-ready NestJS boilerplate with Hexagonal Architecture and Generic Repository Pattern\u003c/strong\u003e\n  \u003c/p\u003e\n  \n  \u003cp\u003e\n    \u003ca href=\"https://github.com/BrahimAbdelli/nestier/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://nodejs.org\"\u003e\u003cimg src=\"https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg\" alt=\"Node\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.typescriptlang.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/typescript-5.9-blue.svg\" alt=\"TypeScript\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://nestjs.com/\"\u003e\u003cimg src=\"https://img.shields.io/badge/nestjs-11.1.12-red.svg\" alt=\"NestJS\"\u003e\u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/version-2.0.1-orange.svg\" alt=\"Version\"\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n---\n\n## What is this?\n\nNestier is a boilerplate that demonstrates how to build scalable NestJS applications using **hexagonal architecture** (ports \u0026 adapters) and the **generic repository pattern**. It provides a solid foundation for enterprise applications with three example modules showcasing different implementation approaches:\n\n| Module | Pattern | Description |\n|--------|---------|-------------|\n| **Category** | Base Implementation | Uses the generic base components directly for simple CRUD |\n| **Product** | Extended Base | Extends base with custom use cases and repository methods |\n| **User** | Custom Implementation | Full custom implementation with JWT authentication and email features |\n\n## Quick Start\n\n```bash\n# Install dependencies\nnpm install\n\n# Set up environment\ncp .env.example .env\n\n# Run the app\nnpm run start:dev\n```\n\nThe API will be available at `http://localhost:3000/api` and Swagger docs at `http://localhost:3000/docs`.\n\n## Architecture\n\nThe project follows a strict **hexagonal architecture** (also known as ports \u0026 adapters) with four distinct layers:\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"./public/architecture-diagram.svg\" alt=\"Architecture Diagram\" width=\"100%\"\u003e\n\u003c/div\u003e\n\n### Layer Responsibilities\n\n| Layer | Purpose | Contents |\n|-------|---------|----------|\n| **Domain** | Business logic \u0026 rules | Entities, Value Objects, Repository Interfaces, Domain Errors |\n| **Application** | Use cases \u0026 orchestration | Services, Use Cases, Port Interfaces |\n| **Infrastructure** | External concerns | TypeORM Repositories, Entity Mappers, Adapters, Middleware |\n| **Presentation** | HTTP interface | Controllers, DTOs, DTO Mappers, Validation |\n\n### Generic Base Pattern\n\nThe base module provides reusable generic components that other modules can extend:\n\n```\nBaseController\u003cT\u003e     →  CRUD endpoints + search + pagination\nBaseService\u003cT\u003e        →  Business logic for all CRUD operations\nBaseRepository\u003cT\u003e     →  Abstract repository interface (port)\nTypeOrmBaseRepository →  Concrete TypeORM implementation (adapter)\nBaseEntity            →  Common entity fields (id, timestamps)\n```\n\n## Project Structure\n\n```\nsrc/\n├── main.ts                      # Application entry point\n├── app.module.ts                # Root module configuration\n├── app.initializer.ts           # Swagger, security, global pipes setup\n│\n├── modules/\n│   ├── base/                    # Generic base module\n│   │   ├── application/\n│   │   │   ├── ports/           # Service \u0026 controller interfaces\n│   │   │   └── services/        # BaseService\u003cT\u003e implementation\n│   │   ├── domain/\n│   │   │   ├── entities/        # BaseEntity\n│   │   │   ├── repositories/    # BaseRepository interface (port)\n│   │   │   └── value-objects/   # Base domain model\n│   │   ├── infrastructure/\n│   │   │   └── adapters/        # TypeOrmBaseRepository (adapter)\n│   │   ├── presentation/\n│   │   │   ├── controllers/     # BaseController factory function\n│   │   │   └── dtos/            # BaseDto, mapper interfaces\n│   │   └── test/                # Testing utilities \u0026 mocks\n│   │\n│   ├── category/                # Simple CRUD example\n│   │   ├── application/         # CategoryService (extends base)\n│   │   ├── domain/              # Category value object, errors\n│   │   ├── infrastructure/      # Entity, mappers\n│   │   ├── presentation/        # Controller, DTOs\n│   │   └── test/                # E2E tests, mocks\n│   │\n│   ├── product/                 # Extended CRUD example\n│   │   ├── application/\n│   │   │   ├── services/        # ProductService\n│   │   │   └── use-cases/       # FindExpensiveProducts, FindByName\n│   │   ├── domain/\n│   │   │   └── repositories/    # ProductRepository interface\n│   │   ├── infrastructure/      # Custom repository implementation\n│   │   ├── presentation/        # Extended controller with custom endpoints\n│   │   └── test/                # E2E tests\n│   │\n│   └── user/                    # Custom auth implementation\n│       ├── application/\n│       │   ├── services/        # UserService, notification adapter\n│       │   └── use-cases/       # SendPasswordResetEmail\n│       ├── domain/\n│       │   ├── ports/           # Email interface (port)\n│       │   ├── repositories/    # UserRepository interface\n│       │   └── value-objects/   # User, Login, ResetPassword\n│       ├── infrastructure/\n│       │   ├── adapters/        # Email adapter, custom repository\n│       │   ├── entities/        # UserEntity\n│       │   ├── mappers/         # AutoMapper profiles\n│       │   └── middleware/      # JWT AuthMiddleware\n│       ├── presentation/        # Auth endpoints, DTOs\n│       └── test/                # E2E tests\n│\n└── shared/\n    ├── common/\n    │   ├── constants/           # Pagination defaults\n    │   ├── email/               # Email service (Mailjet adapter)\n    │   ├── error-handling/      # Exception filters, error mapping\n    │   ├── logger/              # Winston logger service\n    │   ├── pipes/               # Validation pipes\n    │   ├── search/              # Search DTOs and domain models\n    │   ├── types/               # Shared TypeScript types\n    │   ├── utils/               # Utility functions\n    │   └── validators/          # Custom validators\n    │\n    └── config/                  # Configuration management\n        ├── configuration.ts     # Environment-based config\n        ├── database-config.ts   # MongoDB/TypeORM config\n        ├── auth-config.ts       # JWT settings\n        ├── mailjet-config.ts    # Email settings\n        └── models/              # Config type definitions\n```\n\n## Key Features\n\n### Core Architecture\n- **Hexagonal Architecture** - Clean separation of concerns with ports \u0026 adapters\n- **Generic Repository Pattern** - Reusable CRUD operations via TypeORM\n- **Domain-Driven Design** - Rich domain models with value objects\n\n### API Features\n- **JWT Authentication** - Secure authentication with password reset flow\n- **Advanced Search** - Dynamic filtering with multiple comparators (EQUALS, LIKE, etc.)\n- **Pagination** - Built-in pagination support for all list endpoints\n- **Soft Delete** - Archive/unarchive functionality for data preservation\n\n### Infrastructure\n- **AutoMapper** - Automatic entity ↔ domain ↔ DTO mapping\n- **Swagger/OpenAPI** - Auto-generated API documentation\n- **Winston Logger** - Structured logging with multiple transports\n- **Mailjet Integration** - Transactional email with templates\n\n### Security\n- **Helmet** - Security headers\n- **Rate Limiting** - Request throttling (10,000 req/15min)\n- **CORS** - Cross-origin resource sharing\n- **Input Validation** - class-validator with custom pipes\n\n### DevOps\n- **Docker** - Multi-stage build for development and production\n- **Docker Compose** - Full stack with MongoDB and SonarQube\n- **SonarQube** - Code quality and coverage analysis\n- **CI/CD Ready** - GitHub Actions workflow included\n\n## Environment Variables\n\nCreate a `.env` file based on `.env.example`:\n\n```env\n# Server\nSERVER_PORT=3000\nSERVER_HOST=localhost\nNODE_ENV=development\n\n# Database (MongoDB)\nMONGO_URL=mongodb://localhost:27017/nestier\n\n# JWT Authentication\nSECRET=your-super-secret-jwt-key-change-this-in-production\nTOKEN_EXPIRATION=1h\nRESET_PASSWORD_EXPIRATION=24h\nRESET_PASSWORD_URL=http://localhost:3000/reset-password\nSUPPORT_EMAIL=support@example.com\n\n# Email (Mailjet)\nMAILJET_EMAIL=noreply@example.com\nMAILJET_API_KEY=your-mailjet-api-key\nMAILJET_SECRET_KEY=your-mailjet-secret-key\nMAILJET_VERSION=v3.1\nMAILJET_COMPANY_NAME=Your Company Name\n\n# Product Configuration\nRESTRICTED_WORDS=replica,knockoff,counterfeit,imitation\n```\n\n## API Endpoints\n\n### Authentication (User Module)\n\n```bash\n# Sign up\nPOST /api/users/signup\n{ \"username\": \"john\", \"email\": \"john@example.com\", \"password\": \"SecurePass123!\", \"lastname\": \"Doe\" }\n\n# Login\nPOST /api/users/login\n{ \"email\": \"john@example.com\", \"password\": \"SecurePass123!\" }\n\n# Forgot password (sends reset email)\nPOST /api/users/forgot-password/:email\n\n# Reset password\nPOST /api/users/reset-password\n{ \"token\": \"reset-token\", \"password\": \"NewSecurePass123!\" }\n```\n\n### CRUD Operations (All Modules)\n\n```bash\n# Create\nPOST /api/{resource}\n{ \"name\": \"Item Name\", ... }\n\n# Get all\nGET /api/{resource}\n\n# Get paginated\nGET /api/{resource}/paginate?take=10\u0026skip=0\n\n# Get by ID\nGET /api/{resource}/find/:id\n\n# Update\nPUT /api/{resource}/:id\n{ \"name\": \"Updated Name\", ... }\n\n# Archive (soft delete)\nPATCH /api/{resource}/archive/:id\n\n# Unarchive\nPATCH /api/{resource}/unarchive/:id\n\n# Delete (permanent)\nDELETE /api/{resource}/:id\n```\n\n### Advanced Search\n\n```bash\nPOST /api/{resource}/search\n{\n  \"attributes\": [\n    { \"key\": \"name\", \"value\": \"test\", \"comparator\": \"LIKE\" },\n    { \"key\": \"price\", \"value\": 100, \"comparator\": \"GREATER_THAN\" },\n    { \"key\": \"isDeleted\", \"value\": false, \"comparator\": \"EQUALS\" }\n  ],\n  \"orders\": { \"name\": \"ASC\", \"price\": \"DESC\" },\n  \"type\": \"AND\",\n  \"take\": 10,\n  \"skip\": 0,\n  \"isPaginable\": true\n}\n```\n\n### Product-Specific Endpoints\n\n```bash\n# Get expensive products (custom use case)\nGET /api/products/expensive?threshold=1000\n\n# Search products by name\nGET /api/products/search/:name\n```\n\n## Testing\n\n```bash\n# Run unit tests\nnpm test\n\n# Run with coverage\nnpm run test:cov\n\n# Run E2E tests\nnpm run test:e2e\n\n# Watch mode\nnpm run test:watch\n```\n\n## Code Quality\n\n```bash\n# Run linter\nnpm run lint\n\n# Format code\nnpm run format\n\n# Start SonarQube\nnpm run sonar:start\n\n# Run full analysis (tests + coverage + sonar)\nnpm run sonar:analyze\n```\n\n## Docker\n\n```bash\n# Start all services (app + MongoDB + SonarQube)\ndocker-compose up -d\n\n# Start only specific services\ndocker-compose up -d backend mongodb\n\n# View logs\ndocker-compose logs -f backend\n\n# Stop services\ndocker-compose down\n\n# Rebuild\ndocker-compose up -d --build\n```\n\n### Services\n\n| Service | Port | Description |\n|---------|------|-------------|\n| Backend | 3000 | NestJS application |\n| MongoDB | 27017 | Database |\n| SonarQube | 9000 | Code quality dashboard |\n\n## Tech Stack\n\n| Category | Technology |\n|----------|------------|\n| **Framework** | NestJS 10.3.8 |\n| **Language** | TypeScript 5.9 |\n| **Database** | MongoDB 6.x |\n| **ORM** | TypeORM 0.3.x |\n| **Authentication** | JWT (jsonwebtoken) |\n| **Validation** | class-validator, class-transformer |\n| **Mapping** | @automapper/nestjs |\n| **Logging** | Winston |\n| **Email** | Mailjet |\n| **Documentation** | Swagger/OpenAPI |\n| **Testing** | Jest, Supertest |\n| **Code Quality** | ESLint, Prettier, SonarQube |\n| **Containerization** | Docker, Docker Compose |\n\n## Scripts Reference\n\n| Script | Description |\n|--------|-------------|\n| `npm run start:dev` | Start in development mode with hot reload |\n| `npm run start:debug` | Start with debugger attached |\n| `npm run start:prod` | Start production build |\n| `npm run build` | Build the application |\n| `npm test` | Run unit tests |\n| `npm run test:cov` | Run tests with coverage |\n| `npm run test:e2e` | Run E2E tests |\n| `npm run lint` | Run ESLint |\n| `npm run format` | Format with Prettier |\n| `npm run sonar:analyze` | Full SonarQube analysis |\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Author\n\n**Brahim Abdelli**\n- Website: [brahimabdelli.dev](https://brahimabdelli.dev)\n- GitHub: [@BrahimAbdelli](https://github.com/BrahimAbdelli)\n","funding_links":[],"categories":["Resources"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBrahimAbdelli%2Fnestier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FBrahimAbdelli%2Fnestier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBrahimAbdelli%2Fnestier/lists"}