This web app parses and renders data from the planning tool of the faculty in a clean timetable view. It offers powerful filtering by degree, semester, module, event type, status, staff, and location.
- Timetable view (week, day, list) powered by FullCalendar v6
- Tri-state filters (neutral / selected / hidden) across six categories
- Cascading filter counts and active-selection chips
- Degree → semester → module cascade
- Event pinning and pin-group exclusion
- Multiple color modes (type, module, status, staff, custom)
- Shareable links via URL parameters
- Local persistence with
localStorage - Dark mode
- Responsive design with mobile sidebar
- Event detail popup (time, location, staff, status, modules, credits, degrees)
Frontend: HTML, Tailwind CSS v4, Plain JavaScript (ES Modules), FullCalendar v6, Material Icons
Backend: Python, FastAPI, SQLModel (SQLite), BeautifulSoup, httpx
- Python 3.10+
- Node.js (for Tailwind CSS CLI, dev only)
# Clone the repository
git clone https://github.com/natureFrameworkManager/planer.git
cd planer
# Create and activate a virtual environment
python -m venv .venv
# Windows
.venv\Scripts\Activate.ps1
# Linux / macOS
source .venv/bin/activate
# Install Python dependencies
pip install -r requirements.txt
# Install Tailwind CSS CLI (dev only)
npm install# Start the FastAPI server (serves API + frontend)
fastapi run backend/main.pyThe app will be available at http://127.0.0.1:8000.
On startup the backend fetches the latest schedule, parses it, and populates the SQLite database.
npx @tailwindcss/cli -i frontend/css/main.css -o frontend/css/css.css --watchpytestFastAPI provides interactive API documentation out of the box:
- Swagger UI (OpenAPI): http://127.0.0.1:8000/docs
- ReDoc: http://127.0.0.1:8000/redoc
All endpoints are read-only (GET) under /api. CORS is enabled for all origins (GET only).
On startup the backend parses the latest schedule from the faculty website and populates a local SQLite database. The database is automatically cleared and repopulated when a new semester is detected.
| Resource | List | Detail |
|---|---|---|
| Modules | /api/modules |
/api/modules/{id} |
| Events | /api/events |
/api/events/{id} |
| Staff | /api/staff |
/api/staff/{id} |
| Locations | /api/locations |
/api/locations/{id} |
| Degrees | /api/degrees |
/api/degrees/{id} |
| Semesters | /api/semesters |
/api/semesters/{id} |
Every list and detail endpoint supports ?include_relationships=true:
- List endpoints — adds related ID arrays (e.g.
degree_ids,event_ids,module_ids,staff_ids). - Detail endpoints — embeds full nested objects (e.g. modules include their degrees with semester info and their events).
Degree endpoints additionally support ?include_semesters=true to include the list of semesters associated with each degree.
All filters are combined with AND. List parameters (e.g. weekday, type, status) accept multiple values combined with OR.
| Parameter | Description |
|---|---|
name |
Case-insensitive substring match on module name |
module_number |
Case-insensitive substring match on module number |
language |
Case-insensitive substring match on language |
planung |
Case-insensitive substring match on department |
credits_min |
Minimum credits (inclusive) |
credits_max |
Maximum credits (inclusive) |
degree_id |
Filter by associated degree ID |
semester |
Filter by semester number (with degree_id) |
| Parameter | Description |
|---|---|
title |
Case-insensitive substring match on event title |
weekday |
Weekday(s): 1=Monday .. 7=Sunday |
type |
Event type(s), e.g. Vorlesung, Seminar, Übung, Praktikum, ... |
status |
Status(es): ok, pok, tok, alt, reserve |
location_id |
Filter by location ID |
start_time_min |
Events starting at or after this time (HH:MM) |
start_time_max |
Events starting at or before this time (HH:MM) |
end_time_min |
Events ending at or after this time (HH:MM) |
end_time_max |
Events ending at or before this time (HH:MM) |
module_id |
Filter by associated module ID(s) |
staff_id |
Filter by associated staff ID(s) |
degree_id |
Filter by associated degree ID(s) (via modules) |
semester |
Filter by semester number (with degree_id) |
| Endpoint | Parameter | Description |
|---|---|---|
| Staff | name |
Case-insensitive substring match |
| Staff | event_id |
Filter by associated event ID |
| Locations | name |
Case-insensitive substring match |
| Degrees | name |
Case-insensitive substring match |
| Degrees | module_id |
Filter by associated module ID |
| Semesters | name |
Case-insensitive substring match |
Six entities connected by three many-to-many link tables:
Degree ←─ ModuleDegreeLink (+ semester, note) ─→ Module
Module ←─ ModuleEventLink ─→ Event
Event ←─ EventStaffLink ─→ Staff
Event ───→ Location (many-to-one)
Enums:
- Weekday:
1(Monday) –7(Sunday) - Status:
ok·pok(time unconfirmed) ·tok(lecturer unconfirmed) ·alt(carried over) ·reserve(no longer offered) - EventType: Vorlesung · Seminar · Übung · Praktikum · Kolloquium · E-Learning-Veranstaltung · Projektseminar · Schulpraktische Studien · Seminar mit Übungsanteil · Vorlesung mit integrierter Übung · Vorlesung mit seminaristischem Anteil · Kein Typ angegeben
- Parse data from faculty planning tool
- Filtering (status, type, module, degree, person, location)
- Responsive design
- Dark mode
- Generate final timetable from selectable events
- Hide selected events
- Different color styles (type, module, status, staff, custom)
- Shareable links via URL parameters
- Progressive Web App / Offline usage
- Deselect impossible filter combinations without unchecking user selections
- Save selection per client in
localStorage- Create personal link from selection
