Live: https://student-scheduler-tau.vercel.app
A full-stack workforce scheduling platform built for the UMass Boston AV department. Admins upload student availability via iCal export from Google Calendar; the backend runs a probabilistic algorithm across 100,000 iterations to produce and rank the 5 best shift assignments, balancing coverage, hour caps, and student availability density.
- Probabilistic scheduling algorithm — extracts contiguous availability islands from each student's calendar, then uses zero-density weighting to prefer shifts that fill under-covered time slots
- iCal import — students export their Google Calendar as
.ics; the parser converts events into a 96-block-per-day availability matrix (15-minute resolution) - Schedule ranking — the top 5 schedules from 100,000 runs are ranked by number of unfilled shifts and returned to the admin
- Admin dashboard — Next.js interface for uploading student lists, viewing availability, and selecting a final schedule
- Supabase Auth — role-based access with admin and student roles enforced via JWT middleware
- Rate limiting — Redis-backed per-IP rate limiting on all API routes
| Layer | Technologies |
|---|---|
| Backend API | Node.js · Express · Supabase (PostgreSQL) · Redis |
| Auth | Supabase Auth (JWT middleware) |
| Frontend | Next.js · React · Tailwind CSS |
| Testing | Vitest (unit) · Supabase test helpers (integration) |
| Deployment | Docker · Vercel · Railway |
Each student's availability is represented as a list of 7 bitstrings (one per day), where each string has 96 characters representing 15-minute blocks from midnight to midnight. Only blocks between index 28 and 83 (7:00 AM – 9:00 PM) are eligible for scheduling.
Island extraction — for each student/day pair, the algorithm finds all contiguous runs of available blocks. These are called "islands."
Zero-density weighting — each island is scored by how many other students are also available during that window. Islands with lower coverage get higher weight — the algorithm prioritises filling gaps first.
Probabilistic assignment — the algorithm iterates over all students in random order. For each student, it samples a day weighted by island density, then flips a weighted coin based on how close the student is to their maximum hours. This prevents any single run from being deterministic.
After 100,000 runs, schedules are sorted by total unfilled shifts and the top 5 are returned.
CS410-Student-Scheduling-Project/
├── backend/
│ └── server/
│ ├── src/
│ │ ├── routes/ # auth, students, availability, schedules
│ │ ├── middleware/ # requireAuth, requireAdmin, rateLimiter
│ │ ├── services/
│ │ │ ├── scheduler.js # Core probabilistic scheduling algorithm
│ │ │ ├── icalParser.js # iCal → availability matrix conversion
│ │ │ └── icalExporter.js
│ │ └── infrastructure/ # Supabase client, Redis client
│ └── tests/
│ ├── unit/ # Route and service unit tests
│ └── integration/ # Supabase and Redis integration tests
└── front-end/
└── new_landing+admin_page/ # Next.js admin dashboard
├── app/
│ ├── admin/ # Schedule management
│ └── dashboard/ # Availability overview
└── components/ # CalendarGrid, ScheduleViewer, Sidebar
- Node.js 20+
- Supabase project
- Redis instance
cd backend/server
npm installCreate a .env file:
PORT=5000
ALLOWED_ORIGIN=http://localhost:3000
SUPABASE_URL=https://your-project-ref.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
REDIS_URL=redis://localhost:6379npm run devcd front-end/new_landing+admin_page
npm installCreate a .env.local file:
NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
NEXT_PUBLIC_API_URL=http://localhost:5000npm run devdocker-compose up --buildcd backend/server
# Unit tests
npm test
# Integration tests (requires running Supabase and Redis)
npm run test:integration