npm package: @maholan/nestjs-template
Description: MHL NestJS Backend Template — NestJS + Prisma + PostgreSQL + Redis + JWT + Docker
Latest version: 1.0.1

# @maholan/nestjs-template

Production-ready NestJS backend starter — scaffolds a full project with **one command**.

**NestJS 11 · TypeScript · Prisma · PostgreSQL · Redis · JWT · Pino · Docker · Yarn 4**

---

## Quick Start

```bash
npx @maholan/nestjs-template my-app
cd my-app
```

The CLI automatically:

- Copies the template
- Sets `package.json` name to your project name
- Creates `.env` from `.env.example`
- Initializes git
- Enables Corepack (Yarn 4)
- Runs `yarn install`

---

## Getting Started

```bash
# Start PostgreSQL + Redis
docker compose up -d

# Create database tables
yarn prisma:migrate:dev

# Seed admin user
yarn prisma:seed

# Start dev server (http://localhost:3000)
yarn start:dev
```

Swagger docs available at `http://localhost:3000/api/docs` (development only).

---

## What's Included

### Tech Stack

| Layer           | Technology                               |
| --------------- | ---------------------------------------- |
| Framework       | NestJS 11                                |
| Language        | TypeScript (strict mode)                 |
| Database        | PostgreSQL 17 + Prisma ORM               |
| Cache           | Redis 7 (ioredis + cache-manager + Keyv) |
| Queues          | BullMQ (Redis-backed)                    |
| Auth            | JWT (access + refresh tokens) + API Key  |
| Logging         | Pino (structured JSON, file rotation)    |
| Docs            | Swagger / OpenAPI (auto-generated)       |
| Compiler        | SWC (fast builds)                        |
| Package Manager | Yarn 4 (Berry)                           |
| Container       | Docker multi-stage build                 |

### Security

- Helmet (CSP, HSTS, noSniff)
- CORS whitelist
- Rate limiting (ThrottlerGuard)
- Global auth guard (JWT + API Key + `@Public()` bypass)
- Role-based access control (`@Roles('ADMIN')`)
- bcryptjs password hashing (cost 12)
- Cookie-based refresh tokens (httpOnly, sameSite, secure)
- Input validation (whitelist + forbidNonWhitelisted)
- Request body limit (1 MB)

### Project Structure

```
src/
├── main.ts                         # Bootstrap (security, CORS, versioning)
├── app.module.ts                   # Root module
├── common/                         # Shared infrastructure
│   ├── decorators/                 # @Public, @Roles, @CurrentUser, @RequestId
│   ├── dto/                        # Response envelope, pagination
│   ├── filters/                    # AllExceptionsFilter
│   ├── guards/                     # AuthGuard, RolesGuard, ApiKeyGuard
│   ├── interceptors/               # Transform, Timeout, Logging
│   ├── middleware/                  # RequestId
│   └── pipes/                      # ZodValidationPipe
├── config/                         # Zod-validated env config
├── modules/
│   ├── auth/                       # Register, login, refresh, logout
│   ├── users/                      # CRUD users + roles
│   └── health/                     # Liveness / readiness (Terminus)
├── prisma/                         # PrismaModule (global)
└── redis/                          # RedisModule (global)
```

---

## Scripts

| Command            | Description          |
| ------------------ | -------------------- |
| `yarn start:dev`   | Watch mode           |
| `yarn start:debug` | Debug with inspector |
| `yarn build`       | Compile (SWC)        |
| `yarn start:prod`  | Run compiled output  |
| `yarn lint`        | ESLint with auto-fix |
| `yarn format`      | Prettier             |
| `yarn test`        | Unit tests           |
| `yarn test:cov`    | Coverage report      |
| `yarn test:e2e`    | E2E tests            |

### Database

| Command                      | Description                   |
| ---------------------------- | ----------------------------- |
| `yarn prisma:migrate:dev`    | Create & apply migration      |
| `yarn prisma:migrate:deploy` | Apply pending migrations (CI) |
| `yarn prisma:studio`         | Visual DB browser             |
| `yarn prisma:seed`           | Seed data                     |
| `yarn prisma:generate`       | Generate Prisma client        |
| `yarn db:reset`              | Reset DB & re-seed            |

---

## Environment Variables

Copy `.env.example` to `.env` (done automatically by the CLI).

| Variable              | Default       | Description                               |
| --------------------- | ------------- | ----------------------------------------- |
| `NODE_ENV`            | `development` | Environment                               |
| `PORT`                | `3000`        | Server port                               |
| `APP_NAME`            | `ai-hub`      | App name (used in logs)                   |
| `DATABASE_URL`        | —             | PostgreSQL connection string              |
| `REDIS_HOST`          | `localhost`   | Redis host                                |
| `REDIS_PORT`          | `6379`        | Redis port                                |
| `REDIS_PASSWORD`      | —             | Redis password                            |
| `CACHE_TTL`           | `5000`        | Default cache TTL (ms)                    |
| `JWT_SECRET`          | —             | **Min 32 chars** (required in production) |
| `JWT_ACCESS_EXPIRES`  | `15m`         | Access token TTL                          |
| `JWT_REFRESH_EXPIRES` | `7d`          | Refresh token TTL                         |
| `CORS_ORIGINS`        | —             | Allowed origins (comma-separated)         |
| `COOKIE_SECURE`       | `false`       | `true` for HTTPS                          |
| `THROTTLE_TTL`        | `60000`       | Rate limit window (ms)                    |
| `THROTTLE_LIMIT`      | `100`         | Requests per window                       |
| `LOG_DIR`             | `./logs`      | Log file directory                        |

---

## Docker

### Development (database only)

```bash
docker compose up -d          # PostgreSQL + Redis
yarn prisma:migrate:dev
yarn start:dev
```

### Production

```bash
docker build -t my-app .
docker run -p 3000:3000 --env-file .env.production my-app
```

The Dockerfile uses a multi-stage build:

- **Build stage** — installs deps, generates Prisma client, compiles TypeScript
- **Runtime stage** — Node 22 Alpine, non-root user (`nestjs`), tini init, health check
- Migrations run automatically on container start via `docker-entrypoint.sh`

---

## Production Checklist

- [ ] `NODE_ENV=production`
- [ ] `JWT_SECRET` — min 32 chars, **not** the dev default
- [ ] `DATABASE_URL` — points to production DB
- [ ] `CORS_ORIGINS` — actual frontend domain(s)
- [ ] `COOKIE_SECURE=true` (if behind HTTPS)
- [ ] Redis is accessible
- [ ] Log directory is writable / mounted as volume
- [ ] Database migrations are up to date

---

## License

[MIT](LICENSE)