All work

03 — Case study

SRU Timetable

My university’s timetable, finally readable.

My part
I designed and built all of it, front end to deploy
Year
2025 – 2026
Status
Live
The SRU Timetable landing page: choose degree, year and batch to load your timetable

The problem

The official timetable is built for the registrar: every batch, elective and room in one table. Finding out when my next class is, or when I am actually free today, meant squinting at a spreadsheet.

The first version was a tool that read the Excel export and drew a cleaner week. It worked, but you still had to find the right file every time. The rebuild removes that step. You choose your degree, year and batch and the timetable loads. Excel upload stays as a fallback.

What it does

  • My week as a real grid

    Each class gets room to breathe instead of being squeezed into a spreadsheet cell.

  • Free Time

    The same grid flipped to show your gaps: how many free slots, the longest break, day by day.

  • Compare batches

    Pick two batches and see the hours when both are free.

  • Attendance calculator

    A quick check for one course (how many classes can I skip?) or a tracker for the whole term.

  • Exports that are complete

    PNG, PDF or HTML, always the full schedule and never a cropped screenshot.

Try it

The live app loads your real batch. This recreation uses made-up data to show how the Free Time view finds your gaps.

Sample batch · 6 slots × 5 days

Sample weekly timetable with made-up data
TimeMonTueWedThuFri
09:30DBMSR-204DAAR-301OSR-110DBMSR-204free
10:30DBMSR-204freeCNR-204DAAR-301DBMSR-204
11:30freePYLLab 2freefreeELECR-402
12:30OSR-110PYLLab 2freeOSR-110ELECR-402
13:30DAAR-301PYLLab 2DAAR-301freefree
14:30freeCNR-204freeCNR-204free

L lecture · T tutorial · P lab · Sample data, not a real batch

Sample data, not a real batch.

How it works

The browser only ever talks to my backend. The backend fetches the public timetable data, reshapes it, caches it briefly and throws it away. Nothing is stored and nothing is scraped in bulk.

  1. 01BrowserReact 19 · TypeScript
  2. 02My backendFastAPI · reshape · short cache
  3. 03University timetable pagePublic source of truth

An uploaded Excel file goes through the same pipeline, so the front end never knows which source it came from.

{
  "batch": "23CSBTB35",
  "timeSlots": ["09:30", "10:30", "..."],
  "days": ["Monday", "Tuesday", "..."],
  "cells": {
    "Monday": {
      "09:30": { "value": "DBMS (L)\nRoom 204", "isClass": true, "type": "L" }
    }
  }
}
The one shape both sources are reduced to

Engineering decisions

  1. 01

    Two sources, one shape

    Live data and Excel files look nothing alike. I reduce both to a single structure, so the grid, the free-time view, comparison and export are written once.

  2. 02

    The iOS export bug that taught me something

    PNG export came out blank on iPhones. A blob URL does not carry over to the tab Safari opens it in. I rewrote the export path instead of patching around it.

  3. 03

    A health check that lied

    The app kept saying the service was down. My own health endpoint was rejecting HEAD requests. A small bug, but a false “down” banner costs trust.

  4. 04

    Free hosting sleeps

    The backend runs on a free tier that goes to sleep, so I added a warm-up ping. The first request no longer feels broken.

  5. 05

    Tests that do not need the internet

    Vitest covers the free-time maths and the interface. pytest mocks the university requests, so every test runs offline.

Stack

  • React 19
  • TypeScript
  • Vite
  • Tailwind CSS v4
  • FastAPI
  • Pydantic v2
  • httpx
  • openpyxl
  • Vitest
  • pytest

Worth knowing

An independent student project, not affiliated with SR University. For exams, room changes and deadlines, check the official page.

It depends on the university’s public timetable service. When that is down the app says so and offers the Excel upload instead.