Live: wsu-uniplan
Uni-Plan is a web-based university course planning and registration support tool.
Students can search courses, detect timetable conflicts, save/load multiple plans, and generate schedule combinations with Quick Planner.
Admins can review a student's registered schedule and apply override actions (forced registration updates).
- Student/Admin login split
- Uses a shared login API and routes users based on account
role
- Uses a shared login API and routes users based on account
- Course search and filtering
- Search/sort by subject, course number, CRN, instructor, credits, days, and term
- Conflict detection
- Automatically detects time conflicts and highlights them in list and weekly views
- Credit-limit policy
- Student flow blocks schedules above 18 credits
- Admin flow can bypass credit cap via
bypassCreditLimit
- Plan save/load
- Saves plans by (
term,name) and allows reloading saved plans
- Saves plans by (
- Registered plan workflow
- Persists current registration in a reserved plan name:
__registered__
- Persists current registration in a reserved plan name:
- Quick Planner generation
- Group selection: search results are grouped by course code; selecting a group means "I need this course — any section is fine." The planner computes the cartesian product of all selected groups (one section per group) and discards every combination that has a time conflict, returning only valid, conflict-free schedules.
- Supports preferences like Friday off and no morning classes (before 10 AM)
- Supports side-by-side comparison for two generated plans
- PDF export
- Exports schedule grid + selected courses into a downloadable PDF
- React 19
- Vite 7
- React Router
- Tailwind CSS
- html2canvas, jsPDF
- FastAPI
- Uvicorn
- PostgreSQL (psycopg2-binary)
- Pydantic
- bcrypt
- python-dotenv
Uni-Plan uses a React SPA frontend with a FastAPI backend.
- Frontend:
Frontend- Routes:
LoginPage,HomePage,AdminPage /api/*calls are proxied by Vite to backend
- Routes:
- Backend:
Backend- Provides auth, course lookup, plan save/register, admin override, and schedule generation APIs
- Serverless entrypoint:
api/index.py- Loads the FastAPI app from
Backend/main.pyfor deployment
- Loads the FastAPI app from
This architecture gives a no-full-reload user experience for search, filtering, and planning.
Uni-Plan/
├─ Frontend/ # React + Vite
│ ├─ src/
│ │ ├─ pages/ # LoginPage, HomePage, AdminPage
│ │ ├─ components/ # CourseSearch, WeeklySchedule, QuickPlanner,
│ │ │ # MySchedule, ComparePlans, CourseDetails,
│ │ │ # AdminOverride, ExportButton, AvailableSeats,
│ │ │ # ErrorMessage
│ │ └─ utils/ # Conflict/time parsing utilities
│ └─ vite.config.js
├─ Backend/ # FastAPI
│ ├─ routers/ # auth, courses, plans, admin, generator
│ ├─ services/ # plan/auth service logic
│ ├─ schemas/ # request/response models
│ ├─ parsers/ # Course data import scripts
│ ├─ db.py # DB connection
│ └─ main.py # FastAPI app
├─ api/
│ └─ index.py # serverless entrypoint
├─ .github/ # PR template
├─ vercel.json # deployment rewrites/function config
├─ DEMO_SCENARIO.md # step-by-step demo walkthrough
└─ README.md
- Node.js
>= 20.19.0 - pnpm
>= 8 - Python 3.10+ (recommended)
- PostgreSQL connection info
From project root:
pnpm installInstall backend Python dependencies in a virtual environment:
python -m venv .venv
source .venv/bin/activate
pip install -r Backend/requirements.txtSet database env vars in Backend/.env (or runtime environment).
Using discrete DB settings:
DB_HOST=localhost
DB_NAME=your_db
DB_USER=your_user
DB_PASSWORD=your_password
DB_PORT=5432From project root:
source .venv/bin/activate
uvicorn Backend.main:app --reload --host 0.0.0.0 --port 8000In a new terminal, from project root:
pnpm devOpen http://localhost:5173.
Root package.json scripts:
pnpm dev: run frontend dev serverpnpm build: build frontendpnpm preview: preview built frontendpnpm install:all: install workspace dependencies
Frontend-local scripts in Frontend/package.json:
vite,vite build,vite preview,eslint
Base prefix: /api
POST /auth/login- loginPOST /auth/logout- logout
GET /courses/search- search courses- main query params:
q,term_id,limit
- main query params:
POST /plans/save- save a named planGET /plans/load- load a named planGET /plans/list- list saved plans for a userPOST /plans/register- persist registered courses (__registered__)GET /plans/registered- load registered coursesPOST /plans/load-plans- load plan names for a user
GET /admin/plans/list- list a student's plansGET /admin/plans/load- load a student's planGET /admin/plans/registered- load a student's registered coursesPOST /admin/plans/register- force-save a student's registered coursesPOST /admin/plans/save- save a student's named plan
POST /generator/generate-schedules- generate conflict-free schedule combinations
- Credit cap: student flow blocks adding courses above 18 credits.
- Conflicts: conflicting courses can still be added, but warnings/highlights are shown.
- Term mapping: frontend currently uses fixed term IDs (
202601,202609). Fall 2026 data is currently empty — use Spring/Summer 2026 for testing. - Auth storage: session state is stored in browser
localStorage. - CORS: backend currently allows all origins (
allow_origins=["*"]) for development convenience.
Based on vercel.json:
/api/(.*)rewrites to/api/index.py- all other routes rewrite to SPA entry (
index.html) - serverless function includes
Backend/**files
For a step-by-step walkthrough covering every feature, see DEMO_SCENARIO.md.
- Login success/failure and student/admin redirects
- Course search + filter + sorting + pagination
- Conflict rendering in list/grid/banner
- Save/Load/Register flows and data consistency
- Quick Planner generate/compare/apply workflow
- Admin override save behavior
- PDF export layout and content quality