A multiuser past-paper tracking web app for Cambridge IA Engineering students.
Each student marks their own tripos questions as solved or unsolved. Groups let you see how your peers are progressing — a heatmap shows the group's collective solve rate per question, and hovering a cell reveals exactly who has solved it.
Deployed on SRCF (Student-Run Computing Facility).
Personal tracker
- 4 sections: 1P1, 1P2, 1P3, 1P4
- 12 questions × 10 years (2016–2025) per section
- Click any cell to toggle solved / unsolved — no page reload (HTMX)
Groups
- Create a group, invite others, or join public groups from the Discover page
- Private groups are accessible only via direct URL
- Two join modes: auto-approve or admin approval
- Group admins can promote/demote members and manage join requests
Group heatmap
- Cell fill: linear gradient from white (0%) to green (≥ threshold of group solved)
- Cell border: green when you have solved that question
- Hover to see which specific members solved it
- Saturation threshold configurable per group (default: 2/3)
Admin panel (root admin only)
- Generate and revoke invite links
- Reset user passwords, delete accounts
- Delete groups
- Add or remove individual questions from the matrix
Settings
- Change display username (default: CRSID)
- Change password
- Dark mode
Auth
- Registration requires an invite link +
@cam.ac.ukemail - CSRF protection on all forms and HTMX requests
| Layer | Technology |
|---|---|
| Backend | Python 3.13 · Flask 3 |
| Database | PostgreSQL · Flask-SQLAlchemy · Flask-Migrate |
| Auth | Flask-Login · Flask-Bcrypt · Flask-WTF |
| Frontend | HTMX 1.9 (CDN) · Jinja2 · plain CSS |
| Deployment | SRCF · Apache + Passenger WSGI |
| Local dev | uv |
- Python 3.13
- uv (
pip install uvor see uv docs) - PostgreSQL or use SQLite (zero setup, see below)
# 1. Clone and enter the project
git clone <your-repo-url>
cd TriposBuddy
# 2. Install dependencies
uv pip install -r requirements.txt
# 3. Configure environment
cp .env.example .envEdit .env:
# SQLite (simplest — no database install needed)
DATABASE_URL=sqlite:///triposbuddy.db
# OR local PostgreSQL
# DATABASE_URL=postgresql://localhost/triposbuddy_dev
SECRET_KEY=change-me-to-a-long-random-string
FLASK_ENV=developmentflask db upgrade # applies migrations (creates all tables)
flask seed-questions # populates 480 default questions (4×12×10)
flask create-admin you@cam.ac.uk yourusername yourpasswordflask run
# → http://127.0.0.1:5000Log in with the admin account, then go to Admin → Invites → Generate to create an invite link for registering additional users.
# SSH into your SRCF shell
ssh crsid@shell.srcf.net
cd ~/public_html
git clone <your-repo-url> triposbuddy
cd triposbuddy
# Create venv and install
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Configure environment
cp .env.example .env
nano .env # fill in SRCF credentials (see below)SRCF .env:
DATABASE_URL=postgresql://CRSID:YOUR_DB_PASSWORD@postgres/CRSID
SECRET_KEY=<long-random-string>
FLASK_ENV=productionYour SRCF PostgreSQL password is in the control panel. The hostname is always postgres.
# Run migrations and seed on SRCF
flask db upgrade
flask seed-questions
flask create-admin you@cam.ac.uk yourusername yourpasswordPassenger picks up passenger_wsgi.py automatically. Apache is configured via .htaccess in public_html/.
TriposBuddy/
├── passenger_wsgi.py # WSGI entry point (SRCF)
├── requirements.txt # uv-compiled lockfile (pip-compatible)
├── .env.example # environment variable template
│
└── app/
├── __init__.py # app factory + CLI commands
├── models.py # all SQLAlchemy models
├── config.py # dev / prod config
├── extensions.py # extension singletons
│
├── auth/ # /auth — login, logout, register
├── tracker/ # /tracker — personal question tracker
├── groups/ # /groups — groups, heatmap, membership
├── settings/ # /settings — profile, password, dark mode
├── admin/ # /admin — root admin panel
├── notifications/ # /notifications — HTMX polling banner
│
├── templates/ # Jinja2 templates
└── static/css/ # main.css (CSS custom properties + dark mode)
See PROJECT_INDEX.md for the full URL map, model schema, and HTMX patterns.
| Command | Description |
|---|---|
flask db upgrade |
Apply all pending migrations |
flask seed-questions |
Populate default 480 questions |
flask create-admin EMAIL USER PW |
Create the root admin account |
# Add the package with a minimum-version constraint to requirements.txt, then install
uv pip install -r requirements.txtrequirements.txt lists direct dependencies with minimum-version constraints (e.g. flask>=3.0,<4).
pip and uv both resolve the best compatible version available on the target platform — this avoids
the lockfile mismatch that would occur if a uv-compiled exact-pin file is installed on SRCF's older
PyPI mirror.