A production-grade RESTful Task Management API built with Node.js and Express.js, engineered for high performance, scalability, and an exceptional developer experience. This project features multi-core CPU clustering via PM2, robust JWT authentication with OTP email verification, a Redis caching layer, Prisma ORM v7 with PostgreSQL, automated testing suites, Zod request validation, Midtrans payment gateway integration, OpenRouter AI chat assistant, and full Docker containerization.
- Tech Stack & Tools
- Key Features
- API Endpoints Overview
- Midtrans Payment Integration
- OpenRouter AI Assistant
- Zod Request Validation
- Master Routes (Admin Tools)
- Getting Started
- PM2 Process Management
- Docker Deployment
- Testing
- Environment Variables
| Category | Technology / Tools |
|---|---|
| Runtime & Framework | Node.js (v22+), Express.js (v5) |
| Server Management | PM2 (Cluster Mode, Graceful Reload, Memory Auto-Restart) |
| Database & ORM | PostgreSQL 17, Prisma ORM v7 (Adapter-Pg) |
| Caching | Redis 7 (In-Memory Caching, Configurable TTL) |
| Authentication | JWT (Access + Refresh Tokens), Bcrypt, OTP Email Verification |
| Input Validation | Zod v4 (Runtime Schema Validation for All Endpoints) |
| Payment Gateway | Midtrans Snap API (Sandbox / Production via Env Config) |
| AI Assistant | OpenRouter AI (Multi-model API Gateway for Chat Completions) |
| File Storage | Cloudinary Image Upload, Multer Middleware |
| Document Generation | PDFKit (Dynamic PDF Reports for Task Completions) |
| Email Service | EmailJS (Transactional Emails: OTP, Notifications) |
| API Documentation | Swagger / OpenAPI 3.0 (Interactive Docs at /api-docs) |
| Testing | Jest v30 + Supertest (Unit & Integration Tests, Mocked External Services) |
| Code Quality | ESLint v10+ (Flat Config), Prettier, Husky Pre-commit Hooks |
| Containerization | Docker (Multi-stage Build, Non-root User) + Docker Compose |
| Logging | Winston (Daily Rotate File + Console Transport with Request ID) |
| Feature | Description |
|---|---|
| π JWT Auth + OTP Verification | Signup with email OTP verification, login, forgot/reset password with token rotation & refresh tokens. |
| π Team Management | Create teams, manage members with roles (admin / member), upload banners to Cloudinary, set capacity. |
| β Task & Assignment | Full CRUD tasks with importance levels, filtering, pagination, and user assignment/unassignment. |
| π Completion & PDF Reports | Mark tasks complete with automated PDF report generation via PDFKit with download endpoint. |
| π³ Midtrans Payments | Invoice management, payment URL generation, webhook auto-update, polling sync, merchant/buyer role control. |
| π€ AI Chat Assistant | Chat with OpenRouter AI (supports multiple LLM models) via public /api/ai/chat endpoint. |
| β‘ Redis Caching | Configurable TTL caching on GET endpoints for sub-millisecond response times. |
| π‘οΈ Zod Input Validation | Runtime schema validation for all request bodies, params, and queries β clear, type-safe error messages. |
| π§ Master Routes | Admin endpoints protected by MASTER_KEY for database operations: clear all data & seed sample data. |
| π Interactive Swagger Docs | Auto-generated API documentation from JSDoc annotations, hosted at /api-docs. |
| π§ͺ Jest Testing Suite | Comprehensive test coverage with mocked external services (Midtrans, EmailJS, Cloudinary, Redis). |
| π³ Dockerized | Multi-stage Docker build (310MB production image), health checks, non-root user, docker-compose ready. |
| π PM2 Cluster Mode | Auto-scales to all CPU cores, zero-downtime reload, memory-limit restart at 1GB. |
| π Winston Logging | Daily rotated log files with request ID tracking. |
This project includes a fully functional payment gateway powered by Midtrans Snap API, supporting secure online transactions with both sandbox and production environments.
| Step | Description |
|---|---|
| 1. Create Invoice | Merchant creates an invoice for a buyer via POST /api/payments with buyerUserId and price. |
| 2. Get Payment URL | Buyer retrieves a secure Midtrans payment URL via GET /api/payments/:id/payment-url. |
| 3. Complete Payment | Buyer completes payment on the Midtrans hosted payment page. |
| 4. Auto-Update Status | Payment status is automatically updated in the database via Midtrans Webhook or Frontend Polling. |
The Midtrans environment is controlled by the MIDTRANS_IS_PRODUCTION environment variable, not NODE_ENV. This allows you to run the app in production mode while still using sandbox keys for testing.
MIDTRANS_IS_PRODUCTION=false # Uses sandbox API (Midtrans test environment)
MIDTRANS_IS_PRODUCTION=true # Uses production API (requires live keys)| Mechanism | Description | When to Use |
|---|---|---|
| Webhook | Midtrans sends real-time notification to POST /api/payments/webhook |
Production (reliable, automatic) |
| Frontend Polling | Frontend calls POST /api/payments/:id/sync every 5 seconds |
Local Development (when webhook is unavailable) |
Note: Webhook only works when the server is accessible via a public URL (e.g., using ngrok or deployed to a cloud server). For local development, frontend polling ensures status updates still work seamlessly.
This project integrates OpenRouter AI, a unified API gateway that provides access to multiple large language models (LLMs) including GPT-4, Claude, Gemini, and many more.
All API endpoints implement Zod v4 runtime schema validation, ensuring that every request body, parameter, and query string is validated before reaching the controller logic.
Benefits:
- β Type-safe request validation
- β Clear, descriptive error messages
- β Protection against malformed or malicious input
- β Centralized schema definitions for maintainability
Protected admin endpoints for database maintenance, secured by the MASTER_KEY environment variable.
- Node.js (v18 or higher)
- Docker & Docker Compose
- Git
# 1. Clone the repository
git clone https://github.com/zannunakiz/TaskManagementBackend_EstelleBright.git
cd TaskManagementBackend_EstelleBright
# 2. Install dependencies
npm install
# 3. Set up environment variables
cp env.example .env
# Edit .env with your configuration (database, API keys, etc.)
# 4. Generate Prisma client
npx prisma generate
# 5. Push database schema
npx prisma db push
# 6. (Optional) Seed sample data
curl -X POST http://localhost:3001/master/seed \
-H "Content-Type: application/json" \
-d '{"master_key": "your_master_key"}'
# 7. Start development server with hot reload
npm run devThis project uses PM2 as the production process manager for zero-downtime reloads, cluster mode, and automatic restarts.
| Command | Description |
|---|---|
npm run pm2:start |
Start app in production mode (port 3001) |
npm run pm2:start:staging |
Start app in staging mode (port 3002) |
npm run pm2:stop |
Stop the app |
npm run pm2:restart |
Restart the app |
npm run pm2:reload |
Reload app with zero downtime |
npm run pm2:delete |
Delete the app from PM2 |
npm run pm2:logs |
Tail live logs |
npm run pm2:monit |
Open real-time monitoring dashboard |
npm run pm2:status |
Show all running PM2 processes |
- Cluster mode with
maxinstances (one per CPU core) - Max memory restart threshold at 1GB
- Log files written to
./logs/pm2-*.log - Environment-specific ports: production on
3001, staging on3002
The app handles SIGTERM and SIGINT signals in src/app.js to gracefully disconnect Prisma and Redis before exiting β no additional configuration needed.
# Build and start all services (PostgreSQL, Redis, App)
docker compose up -d --build
# Stop all services
docker compose down
# View application logs
docker compose logs -f app
# View all services logs
docker compose logs -f- Multi-stage build: Dependencies installed in builder stage, production image is lean (~310MB)
- Non-root user: Runs as
appuserfor security - Health checks: Automatic container health monitoring
- Database migrations: Auto-executed via
docker-entrypoint.sh - Environment variables: Passed from
.envfile via Docker Compose variable substitution
# Run all tests
npm test
# Run tests with watch mode
npm run test:watch
# Run tests with coverage report
npm run test:coverageThe test suite uses Jest with Supertest for HTTP integration testing. External services (Midtrans, EmailJS, Cloudinary, Redis) are mocked using __mocks__/ for reliable, deterministic tests.
This project implements multiple layers of security to protect against common vulnerabilities.
| Feature | Description |
|---|---|
| JWT Access + Refresh Tokens | Short-lived access tokens (30min default) with refresh token rotation |
| Token Versioning | Invalidate all tokens for a user by incrementing tokenVersion (logout all devices) |
| OTP Email Verification | 6-digit OTP sent via EmailJS for signup verification and password reset |
| Cryptographically Secure OTP | OTPs generated using crypto.randomBytes() (not Math.random()) |
| OTP Brute Force Protection | Account locked for 15 minutes after 5 failed OTP attempts |
| Hashed OTP Storage | All OTPs stored as bcrypt hashes (both verification and reset) |
| Role-Based Access Control | Team-level roles: owner, admin, member with granular permissions |
| Feature | Description |
|---|---|
| Zod Schema Validation | All request bodies, params, and queries validated at runtime |
| String Length Limits | Maximum character limits on all string fields (prevents resource exhaustion) |
| HTML Tag Stripping | XSS prevention via HTML tag removal from string inputs |
| Type Coercion Safety | Numeric IDs validated as positive integers |
| Endpoint Category | Limit | Window |
|---|---|---|
| General API | 100 requests | 15 minutes |
| Authentication | 10 requests | 15 minutes |
| OTP Verification | 5 requests | 15 minutes |
| AI Chat | 20 requests | 15 minutes |
| Master Routes | 3 requests | 15 minutes |
| Webhook | 10 requests | 1 minute |
| Feature | Description |
|---|---|
| Webhook Signature Verification | HMAC-SHA512 signature verification using X-Signature-Key header |
| Timing-Safe Comparison | All secret comparisons use crypto.timingSafeEqual() |
| Midtrans Environment Isolation | Sandbox/production controlled by MIDTRANS_IS_PRODUCTION env var |
| Feature | Description |
|---|---|
| Helmet.js | Security headers: HSTS, X-Frame-Options, X-Content-Type-Options, etc. |
| CORS | Strict origin control in production |
| Environment Validation | Startup check for required secrets (exits if missing) |
| Docker Non-Root User | Application runs as appuser (not root) |
| Container Resource Limits | CPU and memory limits for all services |
| Graceful Shutdown | Proper Prisma/Redis disconnection on SIGTERM/SIGINT |
| Request ID Tracking | Every request tagged with unique ID for audit trail |
| Winston Logging | Structured JSON logs with daily rotation |
- Swagger docs (
/api-docs) are only available in non-production environments - All protected endpoints require
Authorization: Bearer <token>header - Master routes require
MASTER_KEYin request body + rate limiting
| Variable | Description | Required |
|---|---|---|
NODE_ENV |
Application environment | Yes |
PORT |
Server port (default: 3001) | Yes |
DATABASE_URL |
PostgreSQL connection string | Yes |
REDIS_URL |
Redis connection string | Yes |
ACCESS_TOKEN_SECRET |
JWT access token secret | Yes |
REFRESH_TOKEN_SECRET |
JWT refresh token secret | Yes |
MASTER_KEY |
Admin master key for seed/clear | Yes |
SERVER_KEY |
Midtrans server key | Yes |
CLIENT_KEY |
Midtrans client key | Yes |
MERCHANT_ID |
Midtrans merchant ID | Yes |
MIDTRANS_IS_PRODUCTION |
Midtrans environment (true/false) |
Yes |
OPENROUTER_API_KEY |
OpenRouter AI API key | Yes |
EMAILJS_SERVICE_ID |
EmailJS service ID | Yes |
EMAILJS_TEMPLATE_ID |
EmailJS template ID | Yes |
EMAILJS_PUBLIC_KEY |
EmailJS public key | Yes |
EMAILJS_PRIVATE_KEY |
EmailJS private key | Yes |
CLOUDINARY_CLOUD_NAME |
Cloudinary cloud name | Yes |
CLOUDINARY_API_KEY |
Cloudinary API key | Yes |
CLOUDINARY_API_SECRET |
Cloudinary API secret | Yes |
CLOUDINARY_UPLOAD_PRESET |
Cloudinary upload preset | Yes |
TOKEN_EXPIRY |
JWT access token expiry (default: 30m) | No |
REFRESH_TOKEN_EXPIRY |
JWT refresh token expiry (default: 30d) | No |
Made with β€οΈ by Richky Amogus