A simple production-ready web app where admins create projects, add members, assign tasks, and members update task status. The app uses Express REST APIs, JWT authentication, password hashing, SQLite, and a plain HTML/CSS/JavaScript frontend.
team-task-manager/
public/
css/
styles.css
js/
api.js
auth.js
dashboard.js
projects.js
tasks.js
dashboard.html
index.html
login.html
projects.html
signup.html
tasks.html
scripts/
seed.js
src/
config/
db.js
middleware/
auth.js
routes/
authRoutes.js
dashboardRoutes.js
projectRoutes.js
taskRoutes.js
userRoutes.js
utils/
validators.js
.env.example
.gitignore
package.json
Procfile
README.md
server.js
Backend files are in server.js and the src/ folder:
server.js: Express app setup and route mountingsrc/config/db.js: SQLite connection and schema creationsrc/middleware/auth.js: JWT authentication and admin authorizationsrc/routes/authRoutes.js: signup, login, current usersrc/routes/userRoutes.js: admin user/member listingsrc/routes/projectRoutes.js: project creation, listing, member assignmentsrc/routes/taskRoutes.js: task creation, listing, status update, deletesrc/routes/dashboardRoutes.js: task statistics
Frontend files are in public/:
index.html: landing screenlogin.html: user loginsignup.html: user signupdashboard.html: task summary cardsprojects.html: project list, project creation, member assignmenttasks.html: task list, task creation, task status updatespublic/css/styles.css: simple responsive stylingpublic/js/*.js: API helper and page logic
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
role TEXT NOT NULL CHECK(role IN ('Admin', 'Member')) DEFAULT 'Member',
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE projects (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT,
created_by INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE project_members (
project_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
added_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (project_id, user_id),
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
description TEXT,
status TEXT NOT NULL CHECK(status IN ('Pending', 'In Progress', 'Completed')) DEFAULT 'Pending',
due_date TEXT NOT NULL,
project_id INTEGER NOT NULL,
assigned_to INTEGER NOT NULL,
created_by INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
FOREIGN KEY (assigned_to) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE
);- Install Node.js 18 or newer.
- Open a terminal in the project folder.
- Install dependencies:
npm install- Create your environment file:
cp .env.example .envOn Windows PowerShell:
Copy-Item .env.example .env- Edit
.envand set a strongJWT_SECRET. - Create sample data:
npm run seed- Start the server:
npm start- Open:
http://localhost:3000
- Push this project to GitHub.
- Log in to Railway.
- Click New Project.
- Choose Deploy from GitHub repo.
- Select this repository.
- Add environment variables in Railway:
JWT_SECRET=your-long-random-secret
DB_FILE=./database/team_task_manager.sqlite
- Railway will run
npm installandnpm start. - Open the generated Railway URL.
- Optional: run the seed command from Railway shell:
npm run seedNote: Railway filesystems may be ephemeral depending on the plan and service settings. For long-term production data, attach a persistent volume or move to a managed database.
Run:
npm run seedAccounts:
Admin:
Email: admin@example.com
Password: admin123
Member:
Email: asha@example.com
Password: member123
Member:
Email: rahul@example.com
Password: member123
Seeded project:
Website Launch
Seeded tasks:
Create homepage content - In Progress - assigned to Asha Member
Fix mobile menu - Pending and overdue - assigned to Rahul Member
POST /api/auth/signup
POST /api/auth/login
GET /api/auth/me
GET /api/users
GET /api/users/members
GET /api/projects
POST /api/projects
GET /api/projects/:id
POST /api/projects/:id/members
DELETE /api/projects/:id/members/:userId
GET /api/tasks
POST /api/tasks
PATCH /api/tasks/:id/status
DELETE /api/tasks/:id
GET /api/dashboard
-
What is the purpose of this project? Answer: It helps teams create projects, assign tasks, and track progress with Admin and Member roles.
-
Which backend framework is used? Answer: Node.js with Express is used to build REST APIs.
-
Which database is used? Answer: SQLite is used because it is simple, file-based, and easy to set up.
-
How are passwords stored? Answer: Passwords are hashed with bcryptjs before saving them in the database.
-
What is JWT used for? Answer: JWT is used to authenticate users after login and protect API routes.
-
What can an Admin do? Answer: Admins can create projects, add/remove members, assign tasks, update tasks, and view all data.
-
What can a Member do? Answer: Members can view their assigned projects/tasks and update their own task status.
-
How are overdue tasks calculated? Answer: A task is overdue when its due date is before today and its status is not Completed.
-
How are relationships maintained? Answer: Foreign keys connect tasks to users/projects and project members to users/projects.
-
Why is validation important? Answer: Validation prevents missing, invalid, or unsafe data from entering the system.
Start by opening the Team Task Manager homepage and logging in as the admin user. On the dashboard, show the total, completed, pending, and overdue task counts. Then open the Projects page and create a new project with a short description.
Next, view the project details and add a member to the project. Go to the Tasks page, create a task, select the project, assign it to a member, and choose a due date. Show that the task appears in the task list.
Now log out and log in as a member. Open the dashboard to show that the member sees only their assigned task statistics. Go to the Tasks page and update the task status from Pending to In Progress or Completed. Finally, return to the dashboard and explain how the counts change based on task status and due date.
PORT=3000
JWT_SECRET=replace-this-with-a-long-random-secret
DB_FILE=./database/team_task_manager.sqlite
- Keep
JWT_SECRETprivate. - Do not commit
.env. - Use
npm run seedonly for demo/sample data. - The API performs role checks, so hidden frontend buttons are only for user experience, not security.