
UCL Module Selector
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 viewmodule-data.json: modules, prerequisites, exclusions and constraintsshared-catalog.js: catalogue helpers shared across viewsscripts/scrape_source_truth_module_data.py: catalogue and route-page scraperscripts/refresh_module_data.py: regenerates the datasetscripts/audit_source_truth_module_data.py: checks the dataset against its sourceagent_context_files/: the guides the implementation was written against