The big picture
The website is static pages on GitHub Pages. Supabase is the shared memory behind it.
Step by step
Load the roster and timetable Supabase
A setup script put the class list and all 23 first-year class times into a Supabase database.
Students pick their times Website
Each student found their name, ticked every class they could attend (at least five) and dragged them into order of preference. A dashboard showed me who still hadn't answered.
Close and export Laptop
Once submissions closed, everyone's answers were exported to one file for the allocator.
The allocator builds a first draft Laptop
Students with the fewest options are placed first, so they aren't squeezed out by people with plenty of choice.
Then it searches for something better Laptop
The draft gets a penalty score. Big penalties go to hard rules (no one in two rooms at once, no one in a class they can't make, every class covered, no group over the cap). Smaller ones go to preferences (an experienced presenter in each group, even group sizes, people's top choices). It then tries a million small swaps, keeping the ones that lower the score. This technique is called simulated annealing. It runs six times from different random starts and keeps the best.
A human checks it Laptop
I capped groups at five and made a handful of manual fixes for special cases. The result was 102 presentation slots across 23 classes, with no clashes.
Publish the groups GitHub Pages
A script turned the result into a groups page listing who presents where, viewable by class or by person.
Run the week Website
After each class, presenters posted photos to a shared feed that others could like and comment on. Photos were stored in Supabase, and iPhone photos were converted automatically.
The audience gives feedback Website
A QR code on the screen opened a short anonymous survey: pick your class, four quick questions and two optional written answers.
Turn it into a report Website
A report page pooled all 267 responses from 21 classes into bar charts, sorted written comments into positive, constructive and critical, and mixed in feed photos. The browser's own "Save as PDF" made the final document.
The pieces
Simulated annealing
A search method that accepts some worse moves early on to escape dead ends, then settles on the best arrangement.
Far too many possible timetables to check by hand or one by one.
Penalty scoring
Every rule and preference is a weighted penalty, so the algorithm knows which to break first.
Some wishes can't all be met. This makes the trade-offs explicit.
Supabase
Database and photo storage the web pages talk to directly, with rules that stop the public changing the roster or groups.
A shared backend for a one-week project without running a server.
Node.js scripts
Setup, export, allocation and page generation all run on my laptop.
The heavy work runs once, so it doesn't need to be online.
GitHub Pages
Free hosting for the static site.
Zero cost and zero maintenance.
Browser "Save as PDF"
The report is a web page designed to print well.
No PDF library needed.
Trade-offs I chose
- An experienced presenter in every group was a preference, not a rule. Two classes ended up without one because no experienced student could make those times.
- Not everyone presented the same number of times. Most presented twice, some once and a few three or four times, depending on how much availability they gave.
- No logins, to keep sign-up friction at zero for a one-week project. It relied on classmates' honesty.
Class Allocations