A REST API for project and task management built with NestJS, TypeScript and PostgreSQL.
TaskFlow API is a lightweight backend for managing projects, project members, tasks, and task comments. It is designed as a clean portfolio project that demonstrates common backend fundamentals without unnecessary infrastructure.
- User registration, login, and current-user endpoints
- JWT authentication and role-based admin endpoints
- Project CRUD with owner/member authorization
- Project member management by project owners
- Task CRUD with assignee membership validation
- Task search, filtering, sorting, and pagination
- Task comments with own-comment or admin mutation rules
- Project task statistics
- Swagger documentation in development
- PostgreSQL migrations, seed data, Docker, linting, and tests
Node.js, TypeScript, NestJS, PostgreSQL, TypeORM, JWT, bcrypt, class-validator, class-transformer, Swagger/OpenAPI, Jest, Docker, Docker Compose, ESLint, and Prettier.
flowchart LR
C[Client / Swagger] -->|HTTP + JSON| API[NestJS API]
API --> AUTH[Authentication & Authorization]
API --> SVC[Domain Services]
SVC --> ORM[TypeORM]
ORM --> DB[(PostgreSQL)]
erDiagram
USER ||--o{ PROJECT : owns
USER ||--o{ PROJECT_MEMBER : joins
PROJECT ||--o{ PROJECT_MEMBER : has
PROJECT ||--o{ TASK : contains
USER ||--o{ TASK : creates
USER ||--o{ TASK : assigned
TASK ||--o{ COMMENT : has
USER ||--o{ COMMENT : writes
All primary keys are UUIDs. Passwords are stored as bcrypt hashes and never returned by API responses.
Authentication uses JWT bearer tokens. Authorization is enforced separately through guards and service-level ownership/membership checks.
Project access requires ownership or membership. Project member changes require ownership. Task assignees must already belong to the project. Comment updates and deletes are limited to the author unless the current user is an admin.
POST /api/v1/auth/registerPOST /api/v1/auth/loginGET /api/v1/auth/meGET /api/v1/users/mePATCH /api/v1/users/meGET /api/v1/usersadmin onlyGET /api/v1/users/:idadmin onlyPOST /api/v1/projectsGET /api/v1/projectsGET /api/v1/projects/:idPATCH /api/v1/projects/:idDELETE /api/v1/projects/:idGET /api/v1/projects/:id/membersPOST /api/v1/projects/:id/membersDELETE /api/v1/projects/:id/members/:userIdPOST /api/v1/projects/:projectId/tasksGET /api/v1/projects/:projectId/tasksGET /api/v1/tasks/:idPATCH /api/v1/tasks/:idDELETE /api/v1/tasks/:idPOST /api/v1/tasks/:taskId/commentsGET /api/v1/tasks/:taskId/commentsPATCH /api/v1/comments/:idDELETE /api/v1/comments/:idGET /api/v1/projects/:id/statsGET /api/v1/health
npm install
cp .env.example .env
npm run migration:run
npm run seed
npm run start:devThe API runs at http://localhost:3000/api/v1.
Copy .env.example to .env and replace the placeholder values. Use a long random JWT_SECRET outside local development.
docker compose up --buildThe API service connects to PostgreSQL through the Compose service name postgres. The PostgreSQL data directory is persisted in the named postgres_data volume.
To demo Swagger while running through Docker, apply the development override:
docker compose -f docker-compose.yml -f docker-compose.swagger.yml up --buildSwagger will then be available at http://localhost:3000/api/docs.
npm run migration:generate -- src/database/migrations/NameOfMigration
npm run migration:run
npm run migration:revertProduction startup does not use synchronize; the Docker image runs compiled migrations before starting the API.
npm run seedSeed accounts use fake data only:
admin@example.com / Example123!alex@example.com / Example123!jordan@example.com / Example123!taylor@example.com / Example123!
npm run lint
npm run test
npm run test:e2e
npm run buildThe E2E suite uses an in-memory PostgreSQL-compatible adapter through TypeORM so it can run without a local database process.
In non-production environments, Swagger is available at:
http://localhost:3000/api/docs
Bearer authentication is configured in Swagger for protected endpoints.
Register:
curl -X POST http://localhost:3000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"Jamie Reed","email":"jamie@example.com","password":"StrongPassword123!"}'Login:
curl -X POST http://localhost:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"alex@example.com","password":"StrongPassword123!"}'Create a project:
curl -X POST http://localhost:3000/api/v1/projects \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name":"Website Redesign","description":"Refresh the public website."}'Filter tasks:
curl "http://localhost:3000/api/v1/projects/<projectId>/tasks?status=IN_PROGRESS&priority=HIGH&page=1&limit=10&sortBy=createdAt&order=DESC" \
-H "Authorization: Bearer <token>"src/
auth/
comments/
common/
database/
projects/
tasks/
users/
test/
docs/
Implements common API security fundamentals for educational and portfolio purposes: bcrypt password hashing, JWT verification, request DTO validation, Helmet, CORS configuration, authorization checks, generic login errors, and no committed secrets.
NestJS provides modular architecture, dependency injection, TypeScript-first conventions, and clean controller/service separation.
PostgreSQL fits relational data, constraints, joins, transactions, UUID keys, and indexed filtering.
JWT supports bearer-token API authentication with a stateless access-token model. The tradeoff is that access tokens remain valid until expiration unless additional revocation infrastructure is added.
DTO validation keeps request validation at the API boundary, rejects malformed or unexpected input, and makes API contracts clearer.
Docker provides a reproducible runtime, consistent dependencies, and simple API/database orchestration.
Modular NestJS API design, authentication, authorization, relational modeling, migrations, request validation, API documentation, unit tests, E2E tests, Dockerized PostgreSQL, and professional documentation.
There are no refresh tokens, password reset emails, notifications, attachments, audit logs, or real-time updates. Admin behavior is intentionally small and limited to user listing/lookup plus comment moderation.
Add refresh-token rotation, richer project roles, task activity history, OpenAPI response schemas, CI, and a production deployment guide.
MIT