Case study
uniTAD
A UK-based platform where students find housing, jobs, meal plans and events, and pay for tickets and Premium. I joined as a Software Engineering Intern in June 2026 and work across its backend, website and app.
01 — Shape
One FastAPI API runs on Render. The Next.js site on Vercel and the Expo app both call it, and PostgreSQL sits underneath. Alembic owns the schema, so no other tool changes a table.
Next.js site (Vercel) ──┐
├──▶ FastAPI (Render) ──▶ PostgreSQL
Expo app ───────────────┘
02 — Release path
Every merge to main runs GitHub Actions: 344 backend tests in pytest, Vitest on the web and
mobile code, and ESLint. If any of them fail, nothing ships. The backend then deploys to Render and the
site to Vercel.
On the backend, alembic upgrade head runs before Uvicorn starts. A migration is always pushed
before it is applied, so the running image can resolve whatever schema it finds.
03 — Payments
Stripe takes ticket payments and Premium subscriptions. The webhook handler is idempotent, so a retried
event is applied once, and it handles subscriptions that go past_due and payments left incomplete.
04 — An outage
Early on I let local development share the production database, and it took the live site down. I restored service, gave development its own database and wrote a deployment runbook to stop a repeat.
05 — Also
- Organiser emails that are batched, deduplicated and safe to retry. The first send reached a 100-attendee event.
- Analytics that wait for consent. Consent has three states, so the app holds the launch event while the user decides, and data is purged after 365 days.
- The React Compiler flagged 21 real violations in the frontend. I fixed each one rather than suppressing the warnings.
- The Expo app follows the website’s design screen by screen.
The code is private. I’m happy to walk through it, and the runbook, on a call.