A full-stack web application to create constraint-aware class timetables. This repository contains:
- backend/: FastAPI-based backend with the timetable generation logic, models, and routes
- frontend/: Vite + React frontend (development served by Vite)
This README documents how to run the project locally, the exact environment expected by the backend, the API endpoints (with shapes that match the code), and development notes.
- Quick summary
- Repo layout
- Requirements
- Configuration (.env)
- Backend — run & development
- Frontend — run & development
- API reference (selected endpoints)
- Data shapes used by the backend (exact)
- Database
- Troubleshooting & common fixes
- Contributing
- License & contact
- Backend: FastAPI application located at
backend/main.py. The application creates DB tables on startup (seecreate_db_and_tables()). - Frontend: React app using Vite in
frontend/, served bynpm run dev(Vite defaults to port 5173). - The backend allows CORS only for origin
http://localhost:5173by default (seebackend/main.py).
- backend/
- main.py — FastAPI app and CORS config
- database.py — SQLAlchemy engine/session helpers and
create_db_and_tables() - models.py — SQLAlchemy models and Pydantic schemas (Users, Teachers, Classes, Assignments, TimeTable, TimeTableEntry)
- requirements.txt — Python dependencies (FastAPI, uvicorn, SQLAlchemy, ortools, pandas, etc.)
- routes/ — route modules:
- Generate_Table.py — endpoints for generating and fetching timetables
- Add_Teachers.py, Add_Classes.py, Assignment.py, Login.py (routers are included in main.py)
- Generations/ — generation utilities used by the solver
- oauth.py — authentication dependency/helpers
- config.py — loads environment variables from
backend/.envusing python-dotenv
- frontend/
- index.html
- package.json — Vite dev scripts and React dependencies
- src/ — frontend source (React)
- vite.config.js
Backend (development)
- Python 3.8+
- Recommended: create a virtualenv
- Install backend dependencies:
The repository's
pip install -r backend/requirements.txtbackend/requirements.txtincludes (excerpt):- fastapi, uvicorn, SQLAlchemy, sqlmodel, pydantic, pandas, numpy, ortools, python-dotenv, psycopg2-binary (and others)
Frontend
- Node.js (v16+ recommended) and npm or yarn
- Install frontend dependencies from project root:
cd frontend npm install
The backend reads environment variables using backend/config.py. Create backend/.env (or set environment variables) with these names:
- DATABASE_URL — e.g.
sqlite:///./timetables.db(for local dev) or a full Postgres URL - SECRET_KEY — secret used by oauth/token logic
- ACCESS_TOKEN_EXPIRE_MINUTES — integer (e.g.
30) - REFRESH_TOKEN_EXPIRE_DAYS — integer (e.g.
7)
Example backend/.env:
DATABASE_URL=sqlite:///./timetables.db
SECRET_KEY=replace_this_with_a_random_string
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=7
Important: config.py expects ACCESS_TOKEN_EXPIRE_MINUTES and REFRESH_TOKEN_EXPIRE_DAYS to be present and parseable as integers (it does int(os.getenv(...))), otherwise the app will error on startup.
-
Create and activate a virtual environment and install dependencies:
python -m venv .venv source .venv/bin/activate # macOS / Linux .venv\Scripts\activate # Windows PowerShell pip install -r backend/requirements.txt
-
Create
backend/.envwith the required variables (see above). -
Run the FastAPI dev server using uvicorn from the repository root:
uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
- The app registers routers from
backend/routes/*and will callcreate_db_and_tables()at startup to create tables (so your DATABASE_URL should point to a writable DB or an SQLite file).
- The app registers routers from
-
Backend CORS default:
- In
backend/main.pyorigins list is set to["http://localhost:5173"]. If you serve the frontend from a different origin or port, add that origin to the list.
- In
-
From the project root:
cd frontend npm install npm run dev- Vite's dev server defaults to port 5173, which matches the backend's default allowed origin.
-
If the backend runs on a different port than expected, update the frontend's API base URL (where API calls are made) to match
http://localhost:8000(or whichever host/port you use), and ensure backend CORS allows the frontend origin.
Routes are defined in backend/routes/. The Generate_Table router shows the exact endpoints and request/response shapes:
-
GET /timetables
- Description: Fetch all timetables for the authenticated user.
- Authentication: required (the route uses the
UserDepdependency). - Response model (List[TimeTableJson]) — each timetable contains assignments; example item:
{ "id": 1, "name": "My Timetable", "assignments": [ { "id": 1, "assign_id": 10, "day": "Monday", "slot": 1, "subject": "Mathematics", "teacher_name": "Alice", "class_name": "10A" } ] }
-
POST /generate
- Description: Generate a timetable using current user's TeacherClassAssignment records.
- Authentication: required.
- Request body:
Generate_Datamodel (see exact fields below). - Behavior (from code): It selects all TeacherClassAssignment entries that belong to the current authenticated user, then calls the solver
Generate_Timetable(...)inbackend/Generations/utils.py. If successful returns a success message, otherwise raises a 400 with'TimeTable is not possible!'. - Example curl (adjust host/port and authentication):
Note: the field name used in the backend model is exactly
curl -X POST http://localhost:8000/generate \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -d '{ "timetable_name": "Week1", "slotes": 6, "days": ["Monday","Tuesday","Wednesday","Thursday","Friday"] }'
"slotes"(this is the field name defined inbackend/models.py) — keep the same spelling.
-
DELETE /timetables/{id}
- Description: Delete a timetable by id (authenticated user must own timetable).
- Authentication: required.
Other route modules included in main.py:
backend/routes/Login.py— authentication/login endpoints (see oauth.py for token logic)backend/routes/Add_Teachers.py— add/list teachersbackend/routes/Add_Classes.py— add/list classesbackend/routes/Assignment.py— assignment endpoints
All of the above routes are protected by authentication where appropriate; check backend/oauth.py and backend/routes/* to see exact protection and request bodies.
From backend/models.py:
-
Generate_Data (request body for POST /generate):
- Fields:
timetable_name(string)slotes(integer) <-- exact spellingslotesdays(array of WeekDay strings: "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
- Fields:
-
TimeTableJson (returned by GET /timetables):
id(int)name(str)assignments(list of TimeTableEntryJson)
-
TimeTableEntryJson:
id(int)assign_id(int)day(str — one of the WeekDay values above)slot(int)subject(str)teacher_name(str)class_name(str)
-
TeacherClassAssignmentCreate / TeacherCreate / ClassCreate — see
backend/models.pyfor request schemas when creating teachers/classes/assignments.
- The app uses SQLAlchemy (declarative base in
backend/models.py) andbackend/database.pyconstructs the engine fromSQL_DATABASE_URL(the value loaded from environment variableDATABASE_URL). - On startup, the app runs
Base.metadata.create_all(bind=engine)so the tables are created automatically for local dev (e.g., when using SQLite). - Example local DATABASE_URL:
sqlite:///./timetables.db.
If you prefer Postgres, set DATABASE_URL like:
postgresql+psycopg2://<user>:<pass>@<host>:<port>/<dbname>
- Missing env values / app fails on startup:
- config.py calls
int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES")). EnsureACCESS_TOKEN_EXPIRE_MINUTESandREFRESH_TOKEN_EXPIRE_DAYSare set and numeric inbackend/.env.
- config.py calls
- Frontend can't communicate with backend:
- Ensure frontend dev server runs at
http://localhost:5173(Vite default) or add your origin tooriginsinbackend/main.py.
- Ensure frontend dev server runs at
TimeTable is not possible!from /generate:- This indicates the solver couldn't produce a feasible timetable given current assignments/constraints. Check teacher/class assignments and constraints.
- Package versions mismatch:
- Use the versions from
backend/requirements.txtandfrontend/package.jsonto match tested environments.
- Use the versions from
- Fork the repository, create a branch (
git checkout -b feat/your-feature), add tests and documentation, and open a PR. - Keep generator/solver logic testable and independent of HTTP layer.
- Add the README to the repo (commit to
mainor open a PR). - Create
backend/.env.exampleand adocker-compose.ymltuned for this repo. - Update the frontend to read the backend API base URL from an environment variable and document the exact API base path.
Repository owner and maintainer: viswajith275 — open an issue for questions or further changes.