Ariel Fishgang
UCL Module Selector live preview

UCL Module Selector

JavaScriptHTMLCSSPythonData VisualisationData Processing

An interactive module-dependency flowchart for the UCL Natural Sciences degree on the Physics, Mathematics and Statistics route. Selecting a module updates what every other module's status becomes, tracks credits against each year's requirement, and shows a weekly timetable for whatever has been chosen.

Stack: vanilla HTML, CSS and JavaScript with no framework, Python for the data pipeline, hosted on Vercel.


Why I built it

I needed to choose my own modules. The information all exists, split between the module catalogue and a separate timetable system, but nothing put it in one place or helped me visualise what modules a given choice would close off later. Working that out by hand across three years of options is the sort of thing a computer should be doing.

Implementation

The data pipeline

Module data is scraped from UCL's public module catalogue and the Natural Sciences route page into a single module-data.json, currently 62 modules across 17 groups, each carrying credits, term, discipline, prerequisites and exclusions.

Requirements are the difficult part. They are written as prose inside catalogue pages rather than as structured fields, so extracting them means interpreting sentences. A scraper pulls the pages and a refresh script regenerates the dataset from them. A third script audits the result against the source, which exists because data collected this way needs checking rather than trusting.

The flowchart

The graph is drawn by hand in JavaScript with no graph library. Module boxes are positioned over three layout passes, and the dependency arrows between them are routed rather than drawn straight, following lanes and meeting boxes at anchor points instead of cutting across them. Making a dependency graph readable turned out to be most of the work.

Selection logic

Choosing a module recomputes the status of every other module: available, selected, or blocked by something not yet taken. Credits total per year against the requirement, a term filter narrows the view, and a detail panel shows a module's catalogue description alongside what it depends on and what depends on it.

Constraints go beyond prerequisites. The dataset encodes mutual exclusions, including cross-year cases where the Year 2 and Year 3 offerings of the same module cannot both count, and the interface enforces those too.

Timetable

Selected modules can be viewed as a weekly timetable, pulled live from the UCL timetable website rather than stored, so it reflects the actual schedule for whatever is currently selected.

Final thoughts

How it was built

Once again this website was built with AI agents, using both Codex and Claude, working from written guides in agent_context_files/ that describe the flowchart behaviour and the module data format before any of it was implemented. This project continued to refine my AI literacy testing even more limetations and differences between models.

What I would do differently

Stop building on top of design choices that had already gone wrong. Reviewing the structure regularly, rather than extending whatever was already there, would have produced more efficient code and made later features easier to add.

On accuracy

The module data comes from UCL's public catalogue, and the requirements are an interpretation of prose written for humans. That interpretation can be wrong. This is a planning tool, not an authority on what a degree will accept. The next continual steps is to scrape as much data for as many courses as possible to potentially help not just me but students across all universities.


What's in the repo

  • app.js: flowchart layout, connector routing, selection state and the timetable view
  • module-data.json: modules, prerequisites, exclusions and constraints
  • shared-catalog.js: catalogue helpers shared across views
  • scripts/scrape_source_truth_module_data.py: catalogue and route-page scraper
  • scripts/refresh_module_data.py: regenerates the dataset
  • scripts/audit_source_truth_module_data.py: checks the dataset against its source
  • agent_context_files/: the guides the implementation was written against