A production-grade, full-stack MERN application — a Jira-inspired enterprise platform for
project management, workforce tracking, agile collaboration, and AI-powered task generation.
Live Demo • Features • Tech Stack • Getting Started • API Docs • Deployment
- Project Overview
- Problem Statement
- Real-World Use Case & Business Impact
- Why This Project Was Built
- Features
- Tech Stack
- System Architecture
- Database Schema Design
- Frontend Architecture
- Backend Architecture
- Authentication Flow
- AI Integration Flow
- State Management
- Getting Started
- Environment Variables
- API Documentation
- UI/UX Documentation
- Feature Deep Dives
- Security Practices
- Performance Optimizations
- Deployment
- Testing
- Screenshots
- Future Enhancements
- Known Limitations
- Challenges & Lessons Learned
- Scalability Considerations
- Contributing
- FAQ
- Troubleshooting
- Portfolio Highlights
- License
JiraClone is a full-stack, enterprise-grade project management and workforce tracking platform engineered with the MERN stack (MongoDB, Express.js, React.js, Node.js). Inspired by industry leaders like Jira and Asana, it goes beyond basic task management by integrating AI-powered issue generation, employee attendance tracking, timesheet management, burndown analytics, and a full agile development workflow.
This platform is designed for engineering teams, HR departments, product managers, and executives who need a unified system for:
- Managing agile sprints, backlogs, and roadmaps
- Tracking employee productivity and attendance in real time
- Generating intelligent task descriptions using OpenAI/ChatGPT
- Monitoring project health with burndown charts and analytics dashboards
- Managing multi-role access with granular RBAC
This is not a tutorial project. It is a complete, deployable SaaS-grade platform built to enterprise documentation, security, and scalability standards.
Modern software organizations face a fragmented tooling landscape:
- Project management lives in Jira or Trello
- HR and attendance lives in separate HRMS tools
- Timesheets are tracked in spreadsheets or legacy ERP systems
- Task descriptions are written manually, slowing down sprint planning
- Analytics are siloed across multiple dashboards with no unified view
This fragmentation leads to:
- Communication overhead between teams
- Duplicate data entry and version conflicts
- Delayed sprint planning cycles
- Poor visibility into employee productivity and project health
JiraClone solves this by providing one unified, AI-enhanced platform where engineering, HR, and product teams can collaborate, plan, track, and deliver — all in one place.
| Role | How They Use JiraClone |
|---|---|
| 👨💻 Engineering Manager | Sprint planning, burndown tracking, code task assignment |
| 🎯 Product Manager | Roadmap creation, backlog grooming, release tracking |
| 👩💼 HR Manager | Employee attendance, timesheet approval, workforce overview |
| 🧑🤝🧑 Team Member | Task management, time logging, comments, notifications |
| 🔑 Admin | RBAC management, system configuration, user onboarding |
- 30–40% reduction in sprint planning time through AI-generated task descriptions
- Eliminates 2–3 separate tools by consolidating project management + HR tracking
- Real-time analytics enable proactive risk identification and resource reallocation
- Attendance automation reduces manual HR workload by up to 60%
- Single source of truth for project data across all stakeholders
This project was built to:
- Demonstrate full-stack MERN engineering depth — not just CRUD, but real-world architecture decisions, state management patterns, and API design
- Solve a real problem — unified project + workforce management for growing engineering teams
- Showcase AI integration — practical use of the OpenAI API in a production workflow
- Apply enterprise engineering practices — JWT security, RBAC, performance optimization, error handling, and environment-based configurations
- Create a portfolio centerpiece — that goes beyond a to-do app and demonstrates production-level thinking
- ✅ Create and manage multiple projects with metadata (name, key, type, description)
- ✅ Project-level settings, member assignment, and role configuration
- ✅ Project status tracking (Active, Archived, On Hold)
- ✅ Agile Board — Kanban-style drag-and-drop task board (To Do → In Progress → Done)
- ✅ Sprint Planning — Create, start, and complete sprints with time-boxed goals
- ✅ Backlog Management — Prioritized backlog with drag-to-sprint promotion
- ✅ Roadmap View — Visual timeline of sprints and epics
- ✅ Burndown Charts — Real-time sprint burndown analytics
- ✅ Full task lifecycle (Story, Bug, Task, Epic, Sub-task)
- ✅ Priority levels: Critical, High, Medium, Low
- ✅ Status workflows: To Do → In Progress → In Review → Done
- ✅ Task assignment, due dates, story points, and labels
- ✅ File attachment support
- ✅ Employee directory with profile management
- ✅ Department and designation management
- ✅ Employee onboarding and offboarding workflows
- ✅ Role-based access control per project and system level
- ✅ One-click attendance marking (Check-In / Check-Out)
- ✅ Daily, weekly, and monthly attendance reports
- ✅ Timesheet logging with project/task association
- ✅ Manager approval workflow for timesheets
- ✅ Overtime detection and alerts
- ✅ AI Suggest — Generate professional task titles, descriptions, and acceptance criteria via OpenAI GPT
- ✅ Context-aware suggestions based on project type and sprint goal
- ✅ One-click AI content insertion into task forms
- ✅ Threaded comment system on tasks
- ✅ @mention support with notification triggers
- ✅ Activity feed per task and project
- ✅ Real-time notification system (in-app)
- ✅ Executive dashboard with project health KPIs
- ✅ Burndown chart visualization
- ✅ Team velocity tracking
- ✅ Attendance and productivity analytics
- ✅ Workload distribution heatmap
- ✅ JWT-based authentication with refresh tokens
- ✅ Role-Based Access Control (Admin, Manager, Developer, Viewer)
- ✅ Protected routes (frontend + backend)
- ✅ Password hashing with bcrypt
- ✅ Rate limiting and input validation
| Technology | Version | Purpose |
|---|---|---|
| React.js | 18.x | UI framework |
| React Router DOM | 6.x | Client-side routing |
| Tailwind CSS | 3.x | Utility-first styling |
| Axios | 1.x | HTTP client |
| React Context API | — | Global state management |
| React Hook Form | 7.x | Form state & validation |
| Recharts / Chart.js | — | Data visualization |
| React DnD / dnd-kit | — | Drag-and-drop Kanban board |
| Lucide React | — | Icon library |
| Technology | Version | Purpose |
|---|---|---|
| Node.js | 18.x LTS | JavaScript runtime |
| Express.js | 4.x | Web framework |
| MongoDB | 6.x | NoSQL database |
| Mongoose | 7.x | ODM for MongoDB |
| JWT (jsonwebtoken) | 9.x | Authentication tokens |
| bcryptjs | 2.x | Password hashing |
| OpenAI SDK | 4.x | AI task generation |
| Express Validator | 7.x | Input validation |
| Morgan | — | HTTP request logging |
| Helmet | — | Security headers |
| CORS | — | Cross-origin policy |
| Express Rate Limit | — | API rate limiting |
| Dotenv | — | Environment configuration |
| Tool | Purpose |
|---|---|
| MongoDB Atlas | Cloud-hosted database |
| Vercel | Frontend deployment |
| Render / Railway | Backend deployment |
| Git & GitHub | Version control |
| Postman | API testing |
┌─────────────────────────────────────────────────────────────────────┐
│ CLIENT (Browser) │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ React.js Frontend (Vite / CRA) │ │
│ │ ┌─────────────┐ ┌──────────────┐ ┌───────────────────┐ │ │
│ │ │ Pages / │ │ Components │ │ Context / State │ │ │
│ │ │ Routes │ │ (Atomic UI) │ │ Management │ │ │
│ │ └─────────────┘ └──────────────┘ └───────────────────┘ │ │
│ │ ┌────────────────────────────────────────────────────────┐ │ │
│ │ │ Axios HTTP Client │ │ │
│ │ └────────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────┘ │
└──────────────────────────────┬──────────────────────────────────────┘
│ HTTPS / REST API
▼
┌─────────────────────────────────────────────────────────────────────┐
│ SERVER (Node.js / Express) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────────┐ │
│ │ Routes │→ │Middleware│→ │Controllers│→ │ Services │ │
│ │ Layer │ │ Layer │ │ Layer │ │ (Business Logic) │ │
│ └──────────┘ └──────────┘ └──────────┘ └────────────────────┘ │
│ Middleware: Auth JWT │ Rate Limiting │ Validation │ Error Handler │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ OpenAI API Client │ │
│ └────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────┬──────────────────────────────────────┘
│ Mongoose ODM
▼
┌─────────────────────────────────────────────────────────────────────┐
│ MongoDB Atlas (Cloud DB) │
│ Collections: users │ projects │ tasks │ sprints │ attendance │ │
│ timesheets │ comments │ notifications │ employees │
└─────────────────────────────────────────────────────────────────────┘
User Action (Browser)
│
▼
React Component → dispatch action / call API
│
▼
Axios HTTP Request (with JWT Bearer Token)
│
▼
Express Router → Rate Limiter → CORS → Auth Middleware
│
▼
Controller (validate input → call service)
│
▼
Service Layer (business logic)
│
▼
Mongoose Model → MongoDB Atlas
│
▼
Response (JSON) → Axios → React State → UI Update
MongoDB Database: jiraclone_db
├── users
├── projects
├── tasks
├── sprints
├── employees
├── attendance
├── timesheets
├── comments
└── notifications
{
_id: ObjectId,
name: String (required),
email: String (required, unique, indexed),
password: String (hashed, required),
role: Enum ['admin', 'manager', 'developer', 'viewer'],
avatar: String (URL),
department: String,
designation: String,
isActive: Boolean (default: true),
lastLogin: Date,
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
name: String (required),
key: String (unique, e.g. "PROJ"),
description: String,
type: Enum ['scrum', 'kanban', 'business'],
status: Enum ['active', 'archived', 'on-hold'],
owner: ObjectId (ref: 'User'),
members: [{ user: ObjectId, role: String }],
startDate: Date,
endDate: Date,
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
title: String (required),
description: String,
type: Enum ['story', 'bug', 'task', 'epic', 'subtask'],
status: Enum ['todo', 'inprogress', 'inreview', 'done'],
priority: Enum ['critical', 'high', 'medium', 'low'],
project: ObjectId (ref: 'Project', required),
sprint: ObjectId (ref: 'Sprint'),
assignee: ObjectId (ref: 'User'),
reporter: ObjectId (ref: 'User'),
storyPoints: Number,
dueDate: Date,
labels: [String],
attachments: [{ name: String, url: String }],
acceptanceCriteria: String,
aiGenerated: Boolean (default: false),
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
name: String (required),
goal: String,
project: ObjectId (ref: 'Project', required),
status: Enum ['planned', 'active', 'completed'],
startDate: Date,
endDate: Date,
tasks: [ObjectId (ref: 'Task')],
velocity: Number,
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
employee: ObjectId (ref: 'User', required),
date: Date (required),
checkIn: Date,
checkOut: Date,
totalHours: Number,
status: Enum ['present', 'absent', 'half-day', 'leave'],
notes: String,
createdAt: Date
}{
_id: ObjectId,
employee: ObjectId (ref: 'User', required),
project: ObjectId (ref: 'Project'),
task: ObjectId (ref: 'Task'),
date: Date (required),
hoursLogged: Number (required),
description: String,
status: Enum ['pending', 'approved', 'rejected'],
approvedBy: ObjectId (ref: 'User'),
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
task: ObjectId (ref: 'Task', required),
author: ObjectId (ref: 'User', required),
content: String (required),
mentions: [ObjectId (ref: 'User')],
isEdited: Boolean (default: false),
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
recipient: ObjectId (ref: 'User', required),
type: Enum ['task_assigned', 'comment_mention', 'sprint_start', 'approval_needed'],
message: String,
relatedTo: { model: String, id: ObjectId },
isRead: Boolean (default: false),
createdAt: Date
}User ──────────────┬──── owns ────▶ Project
├──── member ───▶ Project
├──── reports ──▶ Task
├──── assigned ─▶ Task
├──── logs ─────▶ Attendance
├──── submits ──▶ Timesheet
├──── writes ───▶ Comment
└──── receives ─▶ Notification
Project ───────────┬──── contains ─▶ Sprint
├──── has ───────▶ Task
└──── tracks ────▶ Timesheet
Sprint ────────────└──── groups ────▶ Task
Task ──────────────├──── has ───────▶ Comment
└──── triggers ──▶ Notification
// Performance-critical indexes
db.users.createIndex({ email: 1 }, { unique: true });
db.tasks.createIndex({ project: 1, status: 1 });
db.tasks.createIndex({ sprint: 1 });
db.tasks.createIndex({ assignee: 1 });
db.attendance.createIndex({ employee: 1, date: -1 });
db.timesheets.createIndex({ employee: 1, date: -1 });
db.notifications.createIndex({ recipient: 1, isRead: 1 });
db.comments.createIndex({ task: 1, createdAt: 1 });client/
├── public/
│ └── index.html
├── src/
│ ├── assets/ # Images, icons, fonts
│ ├── components/ # Reusable UI components
│ │ ├── common/ # Button, Input, Modal, Badge, Avatar
│ │ ├── board/ # KanbanBoard, TaskCard, Column
│ │ ├── sprint/ # SprintCard, SprintForm, BurndownChart
│ │ ├── attendance/ # AttendanceTable, CheckInButton
│ │ ├── timesheet/ # TimesheetForm, TimesheetList
│ │ ├── employee/ # EmployeeCard, EmployeeForm
│ │ ├── notifications/ # NotificationBell, NotificationList
│ │ └── ai/ # AISuggestModal, SuggestButton
│ ├── context/ # React Context providers
│ │ ├── AuthContext.jsx # Auth state & JWT management
│ │ ├── ProjectContext.jsx
│ │ └── NotificationContext.jsx
│ ├── hooks/ # Custom React hooks
│ │ ├── useAuth.js
│ │ ├── useProjects.js
│ │ ├── useTasks.js
│ │ └── useNotifications.js
│ ├── pages/ # Route-level page components
│ │ ├── Auth/ # Login, Register
│ │ ├── Dashboard/
│ │ ├── Projects/
│ │ ├── Board/
│ │ ├── Backlog/
│ │ ├── Sprints/
│ │ ├── Roadmap/
│ │ ├── Tasks/
│ │ ├── Employees/
│ │ ├── Attendance/
│ │ ├── Timesheets/
│ │ └── Analytics/
│ ├── services/ # Axios API service layer
│ │ ├── api.js # Axios instance with interceptors
│ │ ├── authService.js
│ │ ├── projectService.js
│ │ ├── taskService.js
│ │ ├── sprintService.js
│ │ ├── attendanceService.js
│ │ ├── timesheetService.js
│ │ └── aiService.js
│ ├── utils/ # Helpers and formatters
│ │ ├── dateUtils.js
│ │ ├── formatters.js
│ │ └── constants.js
│ ├── routes/ # Route config and ProtectedRoute
│ │ ├── AppRoutes.jsx
│ │ └── ProtectedRoute.jsx
│ ├── App.jsx
│ └── main.jsx
├── .env
├── tailwind.config.js
└── package.json
Page Component (route-level)
├── fetches data via custom hook
├── passes data to smart (container) components
└── smart components → dumb (presentational) components
/ (public)
├── /login
├── /register
└── /app (protected - requires JWT)
├── /app/dashboard
├── /app/projects
│ └── /app/projects/:id
├── /app/board/:projectId
├── /app/backlog/:projectId
├── /app/sprints/:projectId
├── /app/roadmap/:projectId
├── /app/tasks/:id
├── /app/employees
├── /app/attendance
├── /app/timesheets
└── /app/analyticsserver/
├── config/
│ ├── db.js # MongoDB connection
│ └── openai.js # OpenAI client config
├── controllers/ # Request handlers
│ ├── authController.js
│ ├── projectController.js
│ ├── taskController.js
│ ├── sprintController.js
│ ├── attendanceController.js
│ ├── timesheetController.js
│ ├── employeeController.js
│ ├── commentController.js
│ ├── notificationController.js
│ └── aiController.js
├── middleware/
│ ├── authMiddleware.js # JWT verification
│ ├── roleMiddleware.js # RBAC enforcement
│ ├── validate.js # Input validation
│ ├── rateLimiter.js # Rate limiting
│ └── errorHandler.js # Global error handler
├── models/ # Mongoose schemas
│ ├── User.js
│ ├── Project.js
│ ├── Task.js
│ ├── Sprint.js
│ ├── Attendance.js
│ ├── Timesheet.js
│ ├── Comment.js
│ └── Notification.js
├── routes/ # Express routers
│ ├── authRoutes.js
│ ├── projectRoutes.js
│ ├── taskRoutes.js
│ ├── sprintRoutes.js
│ ├── attendanceRoutes.js
│ ├── timesheetRoutes.js
│ ├── employeeRoutes.js
│ ├── commentRoutes.js
│ ├── notificationRoutes.js
│ └── aiRoutes.js
├── services/ # Business logic layer
│ ├── emailService.js
│ ├── notificationService.js
│ └── analyticsService.js
├── utils/
│ ├── generateToken.js
│ ├── asyncHandler.js
│ └── apiResponse.js
├── .env
├── server.js # Entry point
└── package.json
Request → CORS → Helmet → Morgan Logger → JSON Parser → Rate Limiter → Router
│
Auth Middleware (JWT)
│
Role Middleware (RBAC)
│
Input Validation
│
Controller
│
Global Error Handler → Response
┌─────────┐ ┌──────────────┐ ┌──────────────┐
│ Browser │ │ Express │ │ MongoDB │
└────┬────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
│ POST /auth/login │ │
│ { email, password }│ │
│────────────────────>│ │
│ │ findOne({ email }) │
│ │───────────────────────>│
│ │ ◄─── User Document ───│
│ │ │
│ │ bcrypt.compare() │
│ │ ✅ Password match │
│ │ │
│ │ jwt.sign(payload, │
│ │ secret, expiry) │
│ │ │
│ { token, user } │ │
│◄────────────────────│ │
│ │ │
│ Store JWT in │ │
│ localStorage / │ │
│ httpOnly Cookie │ │
│ │ │
│ GET /api/projects │ │
│ Authorization: │ │
│ Bearer <token> │ │
│────────────────────>│ │
│ │ jwt.verify(token) │
│ │ ✅ Valid → req.user │
│ │ │
│ { projects data } │ │
│◄────────────────────│ │
{
"header": { "alg": "HS256", "typ": "JWT" },
"payload": {
"id": "64abc123...",
"email": "user@example.com",
"role": "developer",
"iat": 1699000000,
"exp": 1699086400
}
}| Action | Admin | Manager | Developer | Viewer |
|---|---|---|---|---|
| Create Project | ✅ | ✅ | ❌ | ❌ |
| Delete Project | ✅ | ❌ | ❌ | ❌ |
| Create Task | ✅ | ✅ | ✅ | ❌ |
| Delete Task | ✅ | ✅ | ❌ | ❌ |
| Manage Sprint | ✅ | ✅ | ❌ | ❌ |
| View Analytics | ✅ | ✅ | ✅ | ✅ |
| Manage Employees | ✅ | ✅ | ❌ | ❌ |
| Approve Timesheet | ✅ | ✅ | ❌ | ❌ |
| Mark Attendance | ✅ | ✅ | ✅ | ✅ |
| AI Suggest | ✅ | ✅ | ✅ | ❌ |
User clicks "AI Suggest" on task form
│
▼
AISuggestModal opens
User provides: task context / sprint goal keyword
│
▼
POST /api/ai/suggest
{ context: "...", type: "story" }
│
▼
Server validates request + checks rate limit (5 AI calls/min/user)
│
▼
OpenAI API Call:
Model: gpt-3.5-turbo / gpt-4
System Prompt: "You are an expert agile product owner..."
User Prompt: "Generate a Jira task title, description,
and acceptance criteria for: {context}"
│
▼
OpenAI Response:
{
title: "As a user, I want to...",
description: "Background: ...\nDetails: ...",
acceptanceCriteria: "Given... When... Then..."
}
│
▼
Server formats & returns structured JSON
│
▼
Frontend auto-populates task form fields
User reviews → saves task
aiGenerated: true flag stored in DB
The system uses a structured prompt template to ensure consistent, professional Agile output:
const systemPrompt = `You are a senior Agile product owner with 10 years of experience
writing Jira user stories. Always respond in JSON format with:
{ "title": "", "description": "", "acceptanceCriteria": "" }
Follow user story format: "As a [role], I want [feature] so that [benefit]"
Acceptance criteria should follow Given/When/Then format.`;JiraClone uses React Context API + useReducer for global state, keeping the bundle lightweight without Redux overhead.
AppProvider
├── AuthContext → user, token, login(), logout()
├── ProjectContext → projects[], currentProject, CRUD actions
├── TaskContext → tasks[], filters, CRUD actions
├── SprintContext → sprints[], activeSpint, actions
└── NotificationContext → notifications[], unreadCount, markRead()
Component → useContext(ProjectContext)
→ calls service function (e.g., projectService.create(data))
→ Axios POST /api/projects
→ Response → dispatch({ type: 'ADD_PROJECT', payload })
→ Reducer updates state
→ Component re-renders with new data
Ensure you have the following installed:
node --version # v18.x or higher
npm --version # v9.x or higher
mongod --version # MongoDB 6.x (for local setup)git clone https://github.com/swarajvecha-web/Project-Management.git
cd Project-Management# Install backend dependencies
cd server
npm install
# Install frontend dependencies
cd ../client
npm install# Backend
cp server/.env.example server/.env
# Frontend
cp client/.env.example client/.envEdit the .env files with your actual values (see Environment Variables below).
Option A — MongoDB Atlas (Recommended for production)
- Create a free account at mongodb.com/cloud/atlas
- Create a new cluster (M0 Free Tier is sufficient)
- Create a database user and whitelist your IP
- Copy the connection string into
MONGO_URI
Option B — Local MongoDB
# Start MongoDB locally
mongod --dbpath /data/db
# Your connection string:
MONGO_URI=mongodb://localhost:27017/jiraclone_db- Create an account at platform.openai.com
- Navigate to API Keys → Create new secret key
- Add the key to your
.env:
OPENAI_API_KEY=sk-...
⚠️ The AI Suggest feature requires credits on your OpenAI account. New accounts receive free credits.
# Terminal 1 — Start Backend (from /server)
cd server
npm run dev
# Server runs on http://localhost:5000
# Terminal 2 — Start Frontend (from /client)
cd client
npm start
# App runs on http://localhost:3000# Build frontend for production
cd client
npm run build
# Start backend in production mode
cd server
NODE_ENV=production npm start# ─── Server ───────────────────────────────────────────
NODE_ENV=development
PORT=5000
# ─── MongoDB ──────────────────────────────────────────
MONGO_URI=mongodb+srv://<username>:<password>@cluster0.xxxx.mongodb.net/jiraclone_db?retryWrites=true&w=majority
# ─── JWT Authentication ───────────────────────────────
JWT_SECRET=your_super_secure_jwt_secret_key_minimum_32_chars
JWT_EXPIRES_IN=1d
JWT_REFRESH_SECRET=your_refresh_token_secret_key
JWT_REFRESH_EXPIRES_IN=7d
# ─── OpenAI API ───────────────────────────────────────
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
OPENAI_MODEL=gpt-3.5-turbo
OPENAI_MAX_TOKENS=500
# ─── Frontend URL (for CORS) ──────────────────────────
CLIENT_URL=http://localhost:3000
# ─── Rate Limiting ────────────────────────────────────
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX=100
AI_RATE_LIMIT_MAX=5# ─── Backend API URL ──────────────────────────────────
REACT_APP_API_URL=http://localhost:5000/api
# ─── App Config ───────────────────────────────────────
REACT_APP_NAME=JiraClone
REACT_APP_VERSION=1.0.0
⚠️ NEVER commit.envfiles to version control. They are listed in.gitignore.
Development: http://localhost:5000/api
Production: https://your-backend.render.com/api
All protected routes require:
Authorization: Bearer <JWT_TOKEN>
POST /api/auth/register
Content-Type: application/json
{
"name": "Jane Doe",
"email": "jane@example.com",
"password": "SecurePass123!",
"role": "developer"
}Response 201:
{
"success": true,
"message": "User registered successfully",
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"_id": "64abc123...",
"name": "Jane Doe",
"email": "jane@example.com",
"role": "developer"
}
}
}POST /api/auth/login
Content-Type: application/json
{
"email": "jane@example.com",
"password": "SecurePass123!"
}Response 200:
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": { "_id": "...", "name": "Jane Doe", "role": "developer" }
}
}Error Response 401:
{
"success": false,
"message": "Invalid credentials",
"error": "UNAUTHORIZED"
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/projects |
✅ | Get all user's projects |
| POST | /api/projects |
✅ Manager+ | Create new project |
| GET | /api/projects/:id |
✅ | Get project by ID |
| PUT | /api/projects/:id |
✅ Manager+ | Update project |
| DELETE | /api/projects/:id |
✅ Admin | Delete project |
| POST | /api/projects/:id/members |
✅ Manager+ | Add member to project |
POST /api/projects
Authorization: Bearer <token>
{
"name": "Customer Portal Redesign",
"key": "CPR",
"type": "scrum",
"description": "Full redesign of customer-facing portal",
"startDate": "2024-01-15",
"endDate": "2024-06-30"
}Response 201:
{
"success": true,
"data": {
"_id": "64def456...",
"name": "Customer Portal Redesign",
"key": "CPR",
"type": "scrum",
"status": "active",
"owner": "64abc123...",
"createdAt": "2024-01-10T10:00:00.000Z"
}
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/tasks?project=:id |
✅ | Get tasks by project |
| POST | /api/tasks |
✅ | Create task |
| GET | /api/tasks/:id |
✅ | Get task by ID |
| PUT | /api/tasks/:id |
✅ | Update task |
| DELETE | /api/tasks/:id |
✅ Manager+ | Delete task |
| PATCH | /api/tasks/:id/status |
✅ | Update task status |
| PATCH | /api/tasks/:id/assign |
✅ Manager+ | Assign task |
POST /api/tasks
Authorization: Bearer <token>
{
"title": "Implement OAuth 2.0 login",
"description": "Add Google OAuth login to the portal",
"type": "story",
"priority": "high",
"project": "64def456...",
"sprint": "64ghi789...",
"assignee": "64abc123...",
"storyPoints": 8,
"dueDate": "2024-02-15"
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/sprints?project=:id |
✅ | Get sprints by project |
| POST | /api/sprints |
✅ Manager+ | Create sprint |
| PUT | /api/sprints/:id |
✅ Manager+ | Update sprint |
| PATCH | /api/sprints/:id/start |
✅ Manager+ | Start sprint |
| PATCH | /api/sprints/:id/complete |
✅ Manager+ | Complete sprint |
| GET | /api/sprints/:id/burndown |
✅ | Get burndown data |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/attendance/checkin |
✅ | Mark check-in |
| PATCH | /api/attendance/checkout |
✅ | Mark check-out |
| GET | /api/attendance |
✅ | Get own attendance |
| GET | /api/attendance/all |
✅ Manager+ | Get all employees' attendance |
| GET | /api/attendance/report |
✅ Manager+ | Generate attendance report |
POST /api/attendance/checkin
Authorization: Bearer <token>
{}Response 201:
{
"success": true,
"data": {
"_id": "64xyz789...",
"employee": "64abc123...",
"date": "2024-01-15T00:00:00.000Z",
"checkIn": "2024-01-15T09:02:35.000Z",
"status": "present"
}
}POST /api/ai/suggest
Authorization: Bearer <token>
{
"context": "User authentication with Google OAuth",
"type": "story",
"projectType": "scrum"
}Response 200:
{
"success": true,
"data": {
"title": "As a user, I want to sign in with Google so that I can access the platform without creating a new password",
"description": "Background: Users prefer social login for convenience...\n\nImplementation details: Integrate Google OAuth 2.0...",
"acceptanceCriteria": "Given I am on the login page\nWhen I click 'Continue with Google'\nThen I should be redirected to Google's OAuth consent screen\nAnd upon approval, be logged in and redirected to the dashboard",
"aiGenerated": true
}
}All errors follow this consistent format:
{
"success": false,
"message": "Human-readable error message",
"error": "ERROR_CODE",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
}| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Resource created |
| 400 | Bad request / Validation error |
| 401 | Unauthorized (invalid/missing token) |
| 403 | Forbidden (insufficient role) |
| 404 | Resource not found |
| 429 | Too many requests (rate limited) |
| 500 | Internal server error |
JiraClone uses Tailwind CSS with a custom design system featuring:
- Primary color: Indigo (#6366F1) — buttons, highlights
- Background: Dark Navy (#0F172A) — sidebar, dark elements
- Surface: Slate (#1E293B) — cards, modals
- Text: White / Slate-300 for readable contrast
- Status colors: Green (done), Blue (in progress), Yellow (review), Gray (todo)
The entire application is designed with a dark-first theme using Tailwind's dark mode classes. Benefits:
- Reduced eye strain during long development sessions
- Professional SaaS product aesthetic
- Consistent with tools like VS Code, Linear, and GitHub
The main dashboard presents:
- KPI cards: Open tasks, active sprints, attendance today, pending timesheets
- My Tasks widget: Assignee-filtered task list with priority badges
- Sprint Progress: Visual progress bar for active sprint
- Recent Activity feed: Latest comments, status changes, assignments
- Team Attendance: Today's present/absent summary (for managers)
- Kanban-style columns: To Do | In Progress | In Review | Done
- Drag-and-drop task cards using react-beautiful-dnd / dnd-kit
- Task cards display: title, assignee avatar, priority badge, story points
- Column headers show task count and add-task quick button
- Swimlane view option by assignee or epic
- Backlog lists all unassigned tasks in priority order
- Drag tasks from backlog → sprint modal for sprint assignment
- Sprint cards show: name, dates, progress bar, velocity
- One-click sprint start/complete with confirmation modal
- Calendar view showing present (green) / absent (red) days
- Large Check-In / Check-Out button with timestamp display
- Weekly summary table with total hours per day
- Manager view: full team attendance grid with filter by date/department
- Date picker + project/task selector for logging time
- Inline time entry with description field
- Weekly grid view with total hours calculation
- Status badges: Pending / Approved / Rejected
- Manager approval panel with bulk approve option
- Triggered via ✨ AI Suggest button on task creation form
- Text input for context/keywords
- Loading spinner with "Generating..." state
- Structured output display: Title, Description, Acceptance Criteria
- Insert buttons to auto-populate each field
- Clearly labeled as AI-generated content
- Bell icon in navbar with unread count badge
- Dropdown panel with notification list (timestamp, message, link)
- Notification types: task assigned, comment @mention, sprint started, timesheet pending approval
- Mark all as read / individual mark read actions
- Mobile-first Tailwind breakpoints (sm, md, lg, xl)
- Collapsible sidebar on mobile with hamburger menu
- Touch-friendly drag-and-drop with pointer events
- Stacked layout for tables on small screens
- Bottom navigation bar on mobile for key actions
- User clicks "Create Project" in sidebar
- Modal opens with form: name, key (auto-generated), type, description, dates
- POST
/api/projects→ creates project + auto-assigns creator as Admin member - Project appears in sidebar and projects list
- Default board columns are created automatically
- Task created in backlog with type, priority, description
- AI Suggest optionally generates professional description
- Task assigned to sprint during sprint planning
- Developer moves task across board columns (status updates via PATCH)
- Comments added → notifications triggered for assignee/reporter
- Task completed → sprint velocity updates → burndown chart reflects change
- Employee opens Attendance page
- Check-In button is active at start of workday — one click records timestamp
- Button changes to Check-Out once checked in
- Check-out records end time →
totalHourscalculated automatically - If no check-out by end of day, system flags as incomplete
- Manager can view and correct attendance records
- Employee logs time via form: project, task, date, hours, description
- Submitted timesheets enter Pending state
- Manager reviews in approval panel → Approve or Reject with comment
- Approved timesheets contribute to project billing/reporting
- Employee notified of approval/rejection status
- Comments attached to tasks, sorted by timestamp
- @mention support: typing
@shows user autocomplete dropdown - Mentioned users receive notification
- Comments support edit (with "edited" flag) and delete by author/admin
- Activity feed on task detail page shows comments + status changes
- X-axis: Sprint days (Day 1 → Day N)
- Y-axis: Remaining story points
- Ideal line: Linear burndown from total points to zero
- Actual line: Real remaining points updated as tasks are completed
- Data computed server-side in
/api/sprints/:id/burndown
- Passwords hashed with bcrypt (salt rounds: 12)
- JWT tokens are short-lived (1 day) with separate refresh tokens (7 days)
- Tokens stored in
httpOnlycookies ORAuthorizationheader - Token blacklisting on logout (stored in Redis/DB for production)
- Helmet.js sets secure HTTP headers (X-Content-Type-Options, X-Frame-Options, CSP, HSTS)
- CORS configured to allow only whitelisted origins
- Rate limiting prevents brute-force and DDoS: 100 requests/15 min per IP
- AI endpoint rate limited separately: 5 requests/min per user
- All inputs validated with express-validator on the server
- Client-side validation with React Hook Form + Yup schemas
- MongoDB injection prevented via Mongoose's type casting + sanitization
- XSS prevention via sanitization of user-generated content
- Every protected route checks both authentication (JWT) and authorization (RBAC)
- Project membership verified for all project-specific operations
- Users can only modify their own attendance/timesheet records (except managers)
- All secrets in
.envfiles, never committed to version control .env.exampleprovided with placeholder values- Production secrets managed via deployment platform environment variables
- Code splitting via React.lazy() and Suspense for all page components
- Lazy loading of heavy components (charts, modals)
- Memoization with useMemo and useCallback for expensive computations
- Debounced search inputs to reduce API calls
- Virtualized lists for large task/employee lists (react-window)
- Tailwind CSS purged in production build (minimal CSS bundle)
- Image lazy loading with
loading="lazy"attribute
- MongoDB indexes on all high-frequency query fields
- Pagination on all list endpoints (default: 20 items/page)
- Field projection in Mongoose queries — only fetch required fields
- Lean queries for read-only operations (
.lean()skips Mongoose overhead) - Aggregation pipelines for analytics instead of multiple round trips
- Response compression with
compressionmiddleware (gzip)
// Example: Lean query with field projection and pagination
const tasks = await Task.find({ project: projectId, status: 'inprogress' })
.select('title priority assignee storyPoints dueDate')
.populate('assignee', 'name avatar')
.skip((page - 1) * limit)
.limit(limit)
.lean();app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
res.status(statusCode).json({
success: false,
message: err.message || 'Internal Server Error',
error: err.code || 'SERVER_ERROR',
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
});
});const asyncHandler = (fn) => (req, res, next) =>
Promise.resolve(fn(req, res, next)).catch(next);- Morgan for HTTP request logging (development:
dev, production:combined) - Console logging with structured format in development
- Production: Consider Winston + CloudWatch / Datadog integration
- Push
client/to GitHub - Import repository at vercel.com
- Set build settings:
- Framework: Create React App
- Build Command:
npm run build - Output Directory:
build
- Add environment variables in Vercel dashboard:
REACT_APP_API_URL=https://your-backend.render.com/api - Deploy
- Create a new Web Service at render.com
- Connect your GitHub repository
- Set configuration:
- Build Command:
npm install - Start Command:
node server.js - Root Directory:
server
- Build Command:
- Add all environment variables from
server/.env - Deploy
# Install Railway CLI
npm install -g @railway/cli
# Login and deploy
railway login
railway init
railway upSet environment variables via Railway dashboard.
- Create M10 cluster for production (dedicated resources)
- Enable VPC Peering or IP Whitelist for your deployment platform's IPs
- Create a dedicated database user with minimal required permissions
- Enable MongoDB Atlas Backups (continuous or daily)
- Set up Atlas Alerts for connection spikes and slow queries
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy-frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: cd client && npm ci
- name: Build
run: cd client && npm run build
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
deploy-backend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to Render
run: curl -X POST ${{ secrets.RENDER_DEPLOY_HOOK }}A complete Postman Collection is available for testing all endpoints:
- Import
JiraClone.postman_collection.jsonfrom/docs - Set environment variables:
BASE_URL,TOKEN - Run collection with Collection Runner
Authentication:
- Register with valid/invalid data
- Login with correct/wrong credentials
- Access protected routes without token → 401
- Access admin routes as developer → 403
Task Management:
- Create task with all fields
- Create task without required fields → 400 validation error
- Move task across board columns
- Assign task to team member
AI Suggest:
- Generate suggestion with valid context
- Test rate limiting (> 5 calls/min)
- Insert AI content into form
Attendance:
- Check-in marks timestamp
- Check-out prevents double check-out
- View history
- Invalid JWT token → 401 response
- Expired JWT token → 401 with "Token expired" message
- MongoDB connection failure → 500 with appropriate message
- OpenAI API unavailable → graceful degradation message
- Unit Tests: Jest + Supertest for API endpoint testing
- Integration Tests: MongoDB in-memory with jest-mongodb
- Frontend Tests: React Testing Library for component tests
- E2E Tests: Cypress for critical user journeys (login → create project → create task)
Replace the placeholders below with actual screenshots from your deployed application.
| Page | Preview |
|---|---|
| 🔐 Login |  |
| 📊 Dashboard |  |
| 🗂️ Agile Board |  |
| 📁 Projects List |  |
| ✅ Task Detail |  |
| 🤖 AI Suggest Modal |  |
| ⏰ Attendance |  |
| 📝 Timesheets |  |
| 👥 Employees |  |
| 🔔 Notifications |  |
| 📈 Analytics |  |
| Feature | Priority | Description |
|---|---|---|
| Real-time collaboration | 🔴 High | WebSocket (Socket.io) for live board updates |
| Email notifications | 🔴 High | Nodemailer + template engine for email alerts |
| File uploads | 🟡 Medium | AWS S3 / Cloudinary for task attachments |
| GitHub/GitLab integration | 🟡 Medium | Link commits/PRs to Jira tasks |
| Slack integration | 🟡 Medium | Post sprint updates and mentions to Slack |
| AI sprint planning | 🟡 Medium | Auto-suggest tasks based on sprint goal |
| Two-factor authentication | 🟡 Medium | TOTP-based 2FA |
| Export to PDF/CSV | 🟢 Low | Reports exportable as PDF or spreadsheet |
| Mobile app | 🟢 Low | React Native companion app |
| Automated testing suite | 🟢 Low | Jest + Cypress full coverage |
- No real-time updates: Board does not auto-refresh when teammates move tasks. A page refresh or manual refresh is required. (Planned fix: Socket.io integration)
- Basic file attachments: Attachment URLs must be external links; no built-in file upload storage
- OpenAI dependency: AI Suggest requires valid OpenAI API credits; gracefully disabled if unavailable
- Single-tenant: Not designed for multi-tenant SaaS with organization isolation yet
- No email notifications: In-app notifications only; email delivery planned for future release
-
RBAC complexity: Implementing role-based access that works consistently across both frontend route guards and backend middleware required careful design. Solved by centralizing role logic in a shared middleware factory.
-
Drag-and-drop state sync: Optimistically updating the UI while ensuring the backend API confirms the status change required careful state management with rollback on error.
-
AI response reliability: OpenAI responses occasionally deviate from the requested JSON format. Solved with structured JSON prompting and a try/catch parse-with-fallback strategy.
-
Burndown chart data: Computing burndown required tracking historical story points at sprint start, not just current values. Added
initialPointssnapshot to Sprint schema on sprint start. -
Mongoose populate performance: Deep nested
.populate()chains caused N+1 query problems. Resolved by restructuring queries and using aggregation pipelines for analytics.
- Design the database schema before writing controllers — changing schema mid-development causes cascading refactors
- Centralize error handling from day one — retrofitting a global error handler is painful
- Rate limit AI endpoints separately — AI API costs money and needs stricter limits than regular CRUD
- Context API scales well for medium apps — Redux would be overkill for this project scope
- Index early — adding indexes after data volume grows is always more painful than doing it in schema definition
- Backend is stateless (JWT-based auth) — can be scaled horizontally behind a load balancer
- MongoDB Atlas supports auto-scaling and sharding for large datasets
- Frontend served as static files via CDN (Vercel Edge Network)
Redis Layer:
├── Session/Token blacklist
├── Dashboard analytics (TTL: 5 min)
├── Project member lists (TTL: 10 min)
└── Notification counts (TTL: 30 sec)
- Shard
taskscollection byprojectfield (high-volume collection) - Shard
attendancecollection byemployee+daterange key
When scale demands it, the monolith can be split into:
auth-service— JWT issuance and validationproject-service— projects, tasks, sprintshr-service— employees, attendance, timesheetsnotification-service— all notification deliveryai-service— OpenAI proxy with rate limiting
We welcome contributions! Please read this guide before submitting a PR.
# 1. Fork the repository on GitHub
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/Project-Management.git
# 3. Create a feature branch
git checkout -b feat/your-feature-name
# 4. Make your changes and commit
git commit -m "feat: add your feature description"
# 5. Push and open a Pull Request
git push origin feat/your-feature-name| Prefix | Use Case | Example |
|---|---|---|
feat/ |
New feature | feat/ai-sprint-planning |
fix/ |
Bug fix | fix/attendance-checkout-bug |
docs/ |
Documentation | docs/api-endpoints |
refactor/ |
Code refactoring | refactor/task-controller |
test/ |
Tests | test/auth-middleware |
chore/ |
Dependencies, config | chore/upgrade-mongoose |
<type>(<scope>): <short description>
[optional body]
[optional footer]
Examples:
feat(tasks): add AI-powered description generation
fix(auth): resolve JWT expiry not being checked on refresh
docs(readme): add deployment section for Railway
refactor(attendance): extract check-in logic to service layer
- Formatting: Prettier with default config
- Linting: ESLint with
eslint-config-react-app - Naming: camelCase for variables/functions, PascalCase for components
- API: RESTful naming conventions; plural nouns for collections
- Comments: JSDoc for service functions; inline comments for complex logic
- Branch is up to date with
main - No console.log statements in production code
- API changes documented in PR description
- Self-reviewed the diff before submitting
When reporting bugs, include:
- Environment: OS, Node version, Browser
- Steps to reproduce
- Expected vs actual behavior
- Screenshots (if UI issue)
- Console errors (if applicable)
Q: Can I use this as a template for my own project? A: Yes! The project is MIT licensed. Attribution appreciated but not required.
Q: Is the OpenAI API required to run the app? A: No. The app works fully without it. The AI Suggest button will show a graceful error if the API key is missing or invalid.
Q: How do I run the app without MongoDB Atlas (local setup)?
A: Install MongoDB locally, start mongod, and set MONGO_URI=mongodb://localhost:27017/jiraclone_db in your .env.
Q: What is the default admin account?
A: No default admin is seeded. Register the first user and manually update their role to admin in MongoDB:
db.users.updateOne({ email: "your@email.com" }, { $set: { role: "admin" } })Q: Why Context API instead of Redux? A: For this application's complexity, Context API + useReducer provides sufficient state management without the Redux boilerplate overhead. Redux Toolkit would be a natural upgrade if the app scales significantly.
Error: MongoServerError: bad auth
✅ Fix: Check your MONGO_URI username and password. Ensure the database user has readWrite access.
Error: Cannot find module 'openai'
✅ Fix: cd server && npm install openaiError: CORS policy blocked
✅ Fix: Ensure CLIENT_URL in server/.env exactly matches your frontend URL (no trailing slash)
Error: JWT TokenExpiredError
✅ Fix: Clear localStorage and log in again. Check JWT_EXPIRES_IN is set correctly.
Error: React app not loading after build
✅ Fix: Add homepage field to client/package.json:
{ "homepage": "." }Error: openai.chat is not a function
✅ Fix: Ensure you're using OpenAI SDK v4.x. Update with: npm install openai@latest
- Run
EXPLAINon slow MongoDB queries:db.tasks.find({...}).explain("executionStats") - Enable MongoDB Atlas Performance Advisor for automatic index recommendations
- Use React DevTools Profiler to identify slow component renders
- Compress images before adding as screenshots to the repo
- 🏗️ Full-stack MERN architecture from scratch with proper separation of concerns across 16 major modules
- 🤖 AI integration using OpenAI GPT for practical, production-oriented task generation
- 🔐 Enterprise security — JWT, bcrypt, RBAC, rate limiting, Helmet, CORS
- 📊 Real-time analytics — burndown charts, velocity tracking, attendance reports
- 👥 HR management — attendance and timesheet modules not typically found in project management tools
- 🎨 Dark-themed, responsive UI built entirely with Tailwind CSS
- Custom asyncHandler wrapper eliminates repetitive try/catch in every controller
- Service layer separates business logic from Express route handlers for testability
- MongoDB aggregation pipelines for efficient analytics queries avoiding N+1 problems
- Optimistic UI updates on task drag-and-drop with rollback on API failure
- AI prompt engineering with structured output format for consistent JSON responses
React.js Node.js Express.js MongoDB Mongoose JWT REST API Design
RBAC OpenAI API Tailwind CSS React Context API Custom Hooks Git
API Security Performance Optimization System Design Database Schema Design
Agile Methodologies DevOps / Deployment Technical Documentation
Coming soon — link will be added upon deployment
- Frontend: https://jiraclone.vercel.app (placeholder)
- Backend API: https://jiraclone-api.render.com (placeholder)
Demo Credentials:
Admin: admin@demo.com / Demo@1234
Developer: dev@demo.com / Demo@1234
This project is licensed under the MIT License.
MIT License
Copyright (c) 2024 Swaraj Vecha
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Built with ❤️ by Swaraj Vecha
⭐ If this project helped you, please give it a star on GitHub!