Travis Warren
Full-stack developer
I build data products for sport, from the scrapers that collect the raw data, through the analysis that turns it into insight, to the pages people read. Two of them are live and used every week: an AFL injury record and power rankings for basketball competitions.
Projects
InjuryIQ
AFL injury intelligence. A source-cited record of every AFL injury, club and round, with squad-health comparisons and analysis.
InjuryIQ in numbers
| Data rules enforced by Postgres | 75+ |
| Test files | 271 |
| Data-integrity audit scripts | 27 |
| Clubs ranked on squad health | 18 |
Every AFL injury is captured daily, classified to the OSIICS medical standard and kept current round by round. On top of that record sit squad-health rankings for all 18 clubs, per-round matchup health, player durability tiers and venue travel load.
What I built
- Rules that must hold everywhere live in Postgres, not in application code. CHECK constraints, partial unique indexes and triggers stop bad data from any write path, such as a player holding two ongoing injuries.
- An append-only injury event log, with state columns maintained from it by triggers, so every status change has a recorded source.
- A daily ingest pipeline across the Squiggle API, Footywire lineups and club injury lists. New records are written automatically above a confidence threshold, and everything below goes to a review queue.
- Read-only audit scripts that check data invariants after every round and fail on any drift.
- Row-level security on every public table, rate limiting on public endpoints and structured logging throughout.
Stack
Next.js 16, React 19, TypeScript, Supabase Postgres, Drizzle ORM, Tailwind CSS, Vitest, Python, Vercel
Power Rankings
Power rankings for basketball, from school competitions to the NBL, with a ranking kept for every round.
Power Rankings in numbers
| Competitions collected | 7 |
| Test files | 260 |
| Integrity constraints in Postgres | 66 |
| Bugs with written root cause | 78 |
Results are collected each week from seven competitions, including the AIC, GPS and TAS school leagues, CBSQ tournaments, the U18 SQJBC Premier League and the NBL. Each completed round produces a ranking snapshot, so a team's season can be followed week by week.
What I built
- A rating that weighs win percentage, average margin, strength of schedule and scoring efficiency, with a minimum-games rule so a team isn't ranked on one result.
- Collectors for four different sources (JSON APIs plus Puppeteer scraping for box scores), each validated before anything is written.
- A round state machine. Completing a round generates rankings, round stats and season snapshots in a single database transaction, so a failure leaves nothing half-written.
- Three layers of caching (CDN headers, tagged application caches and pooled connections), tuned to keep hosting and database costs down.
- Removing authentication and the admin UI entirely once they became a security liability. Data operations now run as reviewed scripts.
- A bug ledger in which every diagnosed defect has a written root cause and a regression test.
Stack
Next.js 16, React 19, TypeScript, Prisma 7, PostgreSQL, Tailwind CSS, Vitest, Puppeteer, Vercel
Demonwiki
The history of the Melbourne Football Club, the world's oldest professional sporting club, online since 2009.
Demonwiki in numbers
| Articles | 8,350 |
| Images | 6,200 |
| Online since | 2009 |
A Tiki Wiki site drawing on newspapers, books, interviews and personal memories. I run the infrastructure and keep it upgraded, backed up and online.
What I built
- A Python operations toolkit (boto3) for the AWS Lightsail server and MySQL database, covering provisioning, snapshots and health checks.
- Backup and restore tooling for the MySQL database, with the managed database's daily automatic backups as the recovery path.
- Disaster-recovery runbooks and a documented production baseline.
- Diagnosing and fixing a full-site outage (a 100% full root disk behind CloudFront), with the investigation written up.
Stack
AWS Lightsail, CloudFront, S3, MySQL, Python, Tiki Wiki
How I work
I've led distributed technology teams across regions and time zones, and that shows up in how I build: write things down, make the data trustworthy before making it pretty, and leave a record of why each decision was made.
I work with AI coding agents every day. Both InjuryIQ and Power Rankings run their weekly data operations through scripted Claude Code workflows, with dry runs and human review before anything is written to production.
I'm looking for full-stack developer roles. The best way to reach me is on LinkedIn.