Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

13 Commits

Folders and files

Repository files navigation

📋 Task Tracker Lite

A production-ready, full-stack task management application with role-based access control (RBAC), category organization, admin analytics dashboards, and a clean, dynamic user experience. Built with React 19, Express, TypeScript, PostgreSQL, and Prisma ORM.


📑 Table of Contents


Overview

Task Tracker Lite lets users create, organize, and track tasks across categories with priorities, statuses, and due dates. An admin role provides a system-wide analytics dashboard, user management, and advanced task filtering. The repository is fully containerized and designed to run with a single docker compose up --build after copying an environment template.


Architecture

The application follows a clean layered architecture on the backend and a feature-based structure on the frontend.

┌────────────┐     HTTP/JSON      ┌─────────────────┐      Prisma       ┌────────────┐
│  Frontend  │  ───────────────▶  │   Backend API   │  ───────────────▶ │ PostgreSQL │
│  (React +  │  ◀───────────────  │  (Express + TS) │  ◀─────────────── │            │
│   Vite)    │   localhost:5000   │                 │    db:5432 (Docker)│            │
└────────────┘                    └─────────────────┘                   └────────────┘

Backend layers (request flow):

Route → Validation middleware → Controller → Service → Repository → Prisma → PostgreSQL
                                              ↘ AppError → Error handler → JSON error response
  • Routes define endpoints and attach auth/authorization + validation middleware.
  • Controllers parse the request and shape HTTP responses.
  • Services contain business logic and authorization rules.
  • Repositories encapsulate Prisma database access.
  • Middleware handles authentication (JWT), RBAC authorization, Zod validation, and centralized error handling.

Frontend flow: React Router (layout-based nested routes) → TanStack Query (data fetching/caching) → Axios (API client with JWT interceptor) → React Hook Form + Zod (forms/validation).


Tech Stack

Layer Technology
Frontend React 19, Vite, TypeScript, Tailwind CSS, React Router v7, TanStack Query, React Hook Form, Zod, Axios
Backend Node.js, Express, TypeScript, Prisma ORM, Zod, Helmet, CORS, Morgan, Winston, express-rate-limit
Database PostgreSQL 16
Auth JWT (Bearer tokens), bcrypt password hashing, RBAC (ADMIN / USER)
Tooling ESLint, Prettier, ts-node-dev, Docker, Docker Compose, nginx

Folder Structure

task-tracker-lite/
├── docker-compose.yml          # Orchestrates db, api, frontend
├── .env.example                # Root env template (consumed by compose)
├── README.md
├── backend/
│   ├── Dockerfile              # Multi-stage build + startup (migrate, seed, serve)
│   ├── package.json
│   ├── tsconfig.json           # Main TS config
│   ├── tsconfig.seed.json      # Compiles prisma/seed.ts → dist/seed.js
│   ├── prisma/
│   │   ├── schema.prisma       # Data model
│   │   ├── seed.ts             # Idempotent seed (admin, users, categories, tasks)
│   │   └── migrations/         # Prisma migration history
│   └── src/
│       ├── app.ts              # Express app (middleware, routes)
│       ├── server.ts           # HTTP server + graceful shutdown
│       ├── config/             # env, logger, prisma client
│       ├── routes/             # auth, tasks, categories, admin, health
│       ├── controllers/        # Request handlers
│       ├── services/           # Business logic
│       ├── repositories/       # Data access (Prisma)
│       ├── middleware/         # auth, validation, error handler
│       ├── validations/        # Zod schemas
│       ├── utils/              # jwt, appError, asyncHandler
│       └── types/              # Express type augmentations
└── frontend/
    ├── Dockerfile              # Multi-stage build (Vite) + nginx serve
    ├── nginx.conf              # SPA fallback + /api reverse proxy
    ├── vite.config.ts
    └── src/
        ├── api/                # Axios instance + interceptors
        ├── components/         # admin, tasks, categories, common
        ├── context/            # AuthContext
        ├── hooks/              # useTasks, useCategories, useAdmin
        ├── layouts/            # Auth + Dashboard layouts
        ├── pages/              # auth, dashboard, tasks, categories, admin, profile
        ├── routes/             # ProtectedRoute, AdminRoute, AppRoutes
        ├── services/           # API service modules
        ├── types/              # Shared TS types
        └── validations/        # Zod form schemas

Prerequisites

  • Docker and Docker Compose (Docker Compose v2 recommended) — for the containerized setup.
  • Node.js v20+ and npm — for local development without Docker.
  • PostgreSQL 16 (running locally or in a container) — only required for local (non-Docker) development.

Quick Start (Docker)

The fastest way to get the entire stack running.

# 1. Clone
git clone https://github.com/bhumikabiyani/task-tracker-lite.git
cd task-tracker-lite

# 2. Configure environment
cp .env.example .env
# (optional) edit .env to set a strong JWT_SECRET and POSTGRES_PASSWORD

# 3. Build and start all services
docker compose up --build

# In the background:
docker compose up --build -d

Then visit:

Service URL
Frontend UI http://localhost:3000
Backend API http://localhost:5000/api
Health check http://localhost:5000/api/health

On startup the backend automatically runs migrations, the seed, and then starts the server — no manual DB setup required. Sign in with the default credentials.

Stop & reset everything (including the database volume):

docker compose down -v

Note: If you use the legacy v1 binary, substitute docker-compose (with a hyphen) for docker compose.


Local Development

Run the frontend and backend directly with Node.js (useful for hot-reload iteration).

1. Database

Start a PostgreSQL instance (the Docker DB is convenient):

# Start only the database via Docker
docker compose up -d db
# It exposes PostgreSQL on localhost:5432

Or use any local PostgreSQL 16 instance. Create a database named task_tracker.

2. Backend

cd backend
cp .env.example .env          # edit DATABASE_URL + JWT_SECRET for your local DB
npm install
npx prisma generate           # generate the Prisma Client
npx prisma migrate dev        # apply migrations to the local DB
npm run db:seed               # seed demo data (idempotent)
npm run dev                   # start dev server with hot reload

The backend runs at http://localhost:5000/api.

3. Frontend

cd frontend
cp .env.example .env
npm install
npm run dev                   # Vite dev server

The frontend runs at http://localhost:3000 and expects the backend at http://localhost:5000/api (configurable via VITE_API_BASE_URL).


Environment Variables

Three environment files are used. Never commit real .env files — only .env.example templates are tracked.

Root .env (consumed by docker-compose.yml)

Variable Description Default
POSTGRES_USER PostgreSQL superuser postgres
POSTGRES_PASSWORD PostgreSQL password change_me_to_a_strong_password
POSTGRES_DB Database name task_tracker
DB_PORT Host port for PostgreSQL 5432
NODE_ENV Node environment production
PORT / API_PORT Backend container/host port 5000
JWT_SECRET JWT signing secret (≥12 chars, 32+ recommended) — required
JWT_EXPIRES_IN Token lifetime 1d
CORS_ORIGIN Comma-separated allowed origins http://localhost:3000
LOG_LEVEL error | warn | info | http | debug info
FRONTEND_PORT Host port for the frontend 3000
VITE_API_BASE_URL API URL the browser uses http://localhost:5000/api
VITE_APP_NAME App display name Task Tracker Lite

The backend's DATABASE_URL is constructed by Compose from POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB with the host db (the service name), so credentials never drift between the database and the API.

backend/.env (local dev only)

Variable Description
DATABASE_URL Local Prisma connection string, e.g. postgresql://postgres:postgres@localhost:5432/task_tracker?schema=public
JWT_SECRET JWT signing secret (≥12 chars)
JWT_EXPIRES_IN Token lifetime
CORS_ORIGIN Allowed origin(s); * is fine for local dev
LOG_LEVEL Logging level
PORT / NODE_ENV 5000 / development

frontend/.env (local dev only)

Variable Description
VITE_API_BASE_URL Backend API base URL (no trailing slash)
VITE_APP_NAME App display name
VITE_NODE_ENV Frontend environment tag

Generate a strong JWT secret:

openssl rand -base64 32

Database Migrations

Migrations live in backend/prisma/migrations and are applied automatically:

  • Docker: prisma migrate deploy runs in the container entrypoint before the server starts.
  • Local dev: run npx prisma migrate dev to apply migrations and create new ones as the schema evolves.

After changing schema.prisma, generate a migration locally:

cd backend
npx prisma migrate dev --name <descriptive_name>

Seeding

The seed (backend/prisma/seed.ts) is idempotent — it uses upsert / find-or-create, so it is safe to run repeatedly without destroying user-created data.

  • Docker: runs automatically on every container start via node dist/seed.js (the seed is compiled during the image build so it needs no ts-node in production).
  • Local dev: npm run db:seed (equivalent to npx prisma db seed, which runs the TypeScript source via ts-node).

The seed creates: 1 Admin + 2 standard Users, 3 Categories, and 5 sample Tasks, and prints the credentials to the console.


Default Credentials

Use these to sign in immediately after seeding:

Role Email Password Purpose
Admin admin@example.com Password123 Full access: analytics dashboard, user management, all tasks
Standard User alice@example.com Password123 Standard task lists, search, categorization
Standard User bob@example.com Password123 Task assignment and progress states

⚠️ These are demo credentials for local evaluation only. Change them (or remove the seed) before any real deployment.


API Endpoints

All request bodies and responses are JSON. Protected routes require Authorization: Bearer <JWT>.

Authentication

Method Endpoint Auth Description
POST /api/auth/register Public Register a new standard user. Body: { firstName, lastName, email, password }
POST /api/auth/login Public Authenticate and receive a JWT. Body: { email, password }
GET /api/auth/me Bearer Get the current authenticated user

Categories — all require authentication; create/update/delete are Admin only

Method Endpoint Auth Description
GET /api/categories Bearer List categories
GET /api/categories/:id Bearer Get a category
POST /api/categories Admin Create. Body: { name, description?, color? }
PATCH /api/categories/:id Admin Update a category
DELETE /api/categories/:id Admin Soft-delete a category

Tasks — all require authentication

Regular users see tasks they created or are assigned to; admins see all tasks.

Method Endpoint Auth Description
GET /api/tasks Bearer Paginated, filtered, sorted task list
GET /api/tasks/:id Bearer Get task details
POST /api/tasks Bearer Create a task. Body: { title, dueDate, status?, priority?, categoryId, description?, assignedTo? }
PUT /api/tasks/:id Bearer Update a task. Body: any subset of the create fields
DELETE /api/tasks/:id Bearer Delete a task

Task list query params: page, limit, status, priority, categoryId, search, sortBy, sortOrder

Admin — require authentication and ADMIN role

Method Endpoint Description
GET /api/admin/dashboard System-wide statistics
GET /api/admin/tasks All tasks with advanced filters
GET /api/admin/users All users with task metrics (paginated, searchable)
GET /api/admin/users/:id/tasks Tasks created by / assigned to a user

System

Method Endpoint Auth Description
GET /api/health Public Server + database health

Development Workflow

# Backend (from /backend)
npm run dev          # start with hot reload
npm run build        # compile to dist/ (tsc + tsc-alias)
npm run build:seed   # compile prisma/seed.ts → dist/seed.js
npm run lint         # eslint
npm run lint:fix     # eslint --fix
npm run format       # prettier

# Frontend (from /frontend)
npm run dev          # Vite dev server
npm run build        # production build
npm run preview      # preview the production build

Typical change loop:

  1. Edit backend/prisma/schema.prisma.
  2. npx prisma migrate dev --name <change> (applies + generates migration).
  3. npx prisma generate.
  4. Implement the feature across repository → service → controller → route.
  5. npm run lint and npm run build to verify.
  6. Commit the new migration SQL along with the code.

Troubleshooting

docker compose is not found

You may have the legacy v1 binary. Use docker-compose (hyphen) instead, or install Docker Compose v2.

Backend reports JWT_SECRET must be set

The root .env is missing or JWT_SECRET is empty. Run cp .env.example .env and set a value of at least 12 characters.

Backend cannot connect to the database

  • Docker: ensure the db service is healthy (docker compose ps). The backend uses host db, not localhost.
  • Local dev: confirm DATABASE_URL in backend/.env points to your reachable PostgreSQL instance on localhost:5432.

Login fails with the default credentials

The seed may not have run. In Docker it runs automatically on start; locally run npm run db:seed from the backend directory. Verify the printed credentials.

Port already in use (3000 / 5000 / 5432)

Another process (or a previous container) is holding the port. Either stop it or remap the host port via .env (FRONTEND_PORT, API_PORT, DB_PORT).

Frontend container is unhealthy

The nginx healthcheck pings 127.0.0.1:80. If unhealthy, rebuild the image: docker compose up --build frontend.

Database password changes don't take effect

PostgreSQL stores credentials in the data volume on first init. Change POSTGRES_PASSWORD, then recreate the volume: docker compose down -v && docker compose up --build.

Reset everything

docker compose down -v   # removes containers + the database volume
docker compose up --build

License

This project is provided as-is for educational and evaluation purposes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages