A web-based shift scheduling platform built for small and medium-sized businesses. ShiftSync lets managers create and manage schedules while giving employees the tools to view shifts, request swaps, and communicate with their team — all in one place.
Live Demo: shiftsync13.vercel.app
- Authentication — Secure JWT-based register and login for both managers and employees
- Team Management — Managers can create teams and invite employees via a join code
- Shift Scheduling — Weekly grid view to create, assign, and delete shifts with density heat mapping
- Shift Requests — Employees can request time off or shift swaps; managers can approve or deny
- Employee Schedule View — Employees see their own shifts highlighted alongside coworker shifts
- Modern UI — Smooth animations, glassmorphism navbar, responsive design with orange brand theme
| Layer | Technology |
|---|---|
| Frontend | Next.js 16 (TypeScript) with App Router |
| Backend | Express.js (TypeScript) REST API |
| Database | PostgreSQL (Neon) |
| Auth | JWT-based authentication |
| Deployment | Vercel (frontend) · Render (backend) |
├── frontend/ # Next.js app (port 3000)
│ ├── src/app/ # App Router pages
│ ├── src/components/# Shared components (Navbar)
│ └── public/ # Static assets (logo)
├── backend/ # Express API (port 5000)
│ ├── src/routes/ # API route handlers
│ ├── src/middleware/ # Auth middleware
│ └── src/config/ # Database config
├── render.yaml # Render deployment config
└── README.md
- Node.js 18+
- PostgreSQL installed and running
- npm
git clone https://github.com/TAndronaco/CS4800-Worker-Schedule-Project.git
cd CS4800-Worker-Schedule-Projectcd backend
cp .env.example .env
npm install
npm run dev # Runs on http://localhost:5000Edit .env with your database credentials:
DATABASE_URL=postgresql://postgres:yourpassword@localhost:5432/shiftsync
JWT_SECRET=your-secret-key-here
PORT=5000
FRONTEND_URL=http://localhost:3000
NODE_ENV=developmentcd frontend
cp .env.local.example .env.local
npm install
npm run dev # Runs on http://localhost:3000Create a PostgreSQL database called shiftsync:
psql -U postgres -c "CREATE DATABASE shiftsync;"Then run the setup script to create all tables:
psql -U postgres -d shiftsync -f backend/db/schema.sqlIf a schema file is not available, see Database Schema below for the full SQL.
| Method | Endpoint | Description | Access |
|---|---|---|---|
| GET | /api/health |
Health check | Public |
| POST | /api/auth/register |
Register a new user | Public |
| POST | /api/auth/login |
Login | Public |
| GET | /api/teams |
Get user's teams | Auth |
| POST | /api/teams |
Create a team | Manager |
| POST | /api/teams/join |
Join a team via code | Auth |
| GET | /api/shifts |
Get shifts | Auth |
| POST | /api/shifts |
Create a shift | Manager |
| DELETE | /api/shifts/:id |
Delete a shift | Manager |
| GET | /api/requests |
Get requests | Auth |
| POST | /api/requests |
Create a request | Auth |
| PATCH | /api/requests/:id |
Approve or deny a request | Manager |
Click to expand full SQL schema
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
role VARCHAR(20) NOT NULL DEFAULT 'employee',
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE teams (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
join_code VARCHAR(20) UNIQUE NOT NULL,
manager_id INTEGER REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE team_members (
team_id INTEGER REFERENCES teams(id),
user_id INTEGER REFERENCES users(id),
PRIMARY KEY (team_id, user_id)
);
CREATE TABLE shifts (
id SERIAL PRIMARY KEY,
team_id INTEGER REFERENCES teams(id),
employee_id INTEGER REFERENCES users(id),
date DATE NOT NULL,
start_time TIME NOT NULL,
end_time TIME NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE shift_requests (
id SERIAL PRIMARY KEY,
type VARCHAR(20) NOT NULL,
requester_id INTEGER REFERENCES users(id),
shift_id INTEGER REFERENCES shifts(id),
target_shift_id INTEGER REFERENCES shifts(id),
status VARCHAR(20) DEFAULT 'pending',
reason TEXT,
created_at TIMESTAMP DEFAULT NOW()
);