- Migrated accounts
- 6 300+
- Matches integrated
- 17 841
- Tournaments indexed
- 445
Context
A fantasy tennis game: users build a team of real ATP/WTA players for real tournaments, apply bonuses, score points from real results and compete in leagues. Public product on mobile, admin console on web.
Scope
Complete takeover of an existing product, already live with its users: migrating the whole stack and the accounts, rebuilding the game logic, shipping a new mobile app and automating the tennis data ingestion. An end-to-end scope, from the database to the mobile app and its release on both stores. My first mobile app published on the App Store and Google Play.
Product decisions
- Project taken over from a Firebase V1 with an Ionic/Angular mobile app built on Capacitor, fully migrated to a Node, tRPC and PostgreSQL stack
- Existing users carried over without friction: V1 accounts move to the new auth system with no password reset
- Documented benchmarks of tennis data sources before choosing the scraping strategy
- New version shipped to production: a new game mode, richer content and a monetization system
Highlights
- Monorepo with 4 apps (web, mobile, API, marketing) plus a Python scraper in production
- Jobs, crons and scraping powering the tennis data ingestion
- Real-time messaging within leagues, powered by WebSocket and Redis Pub/Sub
- Mobile app built with Expo, deployed through EAS and available on the App Store and Google Play
- Web deployed on Cloudflare Workers, API on Railway, tests colocated in 3 workspaces
Stack
TypeScript
React
React Native
Expo
Hono
tRPC
Better Auth
Drizzle
PostgreSQL
Redis
WebSocket
Cloudflare
Railway
Stripe
RevenueCat
TypeSafe AI