Fantasy Voley
A fantasy league for Spanish volleyball, with real users and a scraper that has to behave.
- Year
- 2024 — present
- Role
- Sole engineer — data ingestion, API, front end
- Stack
- Python PostgreSQL Neon Railway Vue
Problem
Spanish volleyball has a passionate following and no fantasy league. The federation publishes squads and results through a legacy ASP.NET portal with no API, unstable team identifiers, and markup that changes between seasons.
Approach
I built an ingestion layer that treats the federation portal as a hostile data source: player identifiers are stable and used as the join key, team identifiers are not and are resolved per season. Scraping runs on a schedule, writes to a staging table, and only promotes a season once the row counts look sane — so a silent markup change degrades into "no update" instead of "everyone's squad is empty".
Outcome
A working league with real players in it, refreshed automatically through the season, and a data model that survived a federation site redesign without a rewrite.
The lesson: trust nothing upstream
Every scraper eventually breaks. The difference between a weekend project and something people use is what happens when it does. Here, a validation gate between staging and live means a broken parse is visible as stale data, not as corrupted data — which is always the cheaper failure.
Add the numbers when you have them: registered users, matches ingested, seasons covered.