Overview
FudbalLive is a cross platform mobile app where friends form private groups and compete by predicting live football outcomes. I led a team of three frontend engineers and built it from scratch, owning the architecture, the React Native (Expo) foundation, and the full release pipeline to both stores. Live across multiple European leagues and shipped to both the App Store and Google Play.
![]()
The Problem
Football fans had no fun, social first way to compete on match predictions with friends in real time. Existing platforms were too complex, desktop only, or missing the group competition angle, none combined live odds, social groups, and a clean mobile UX.
What I Built
Disclosure: app is ownership of the company that I worked for. As Frontend Lead I set the codebase architecture and engineering standards, planned and delegated work across the three person team, and personally owned the highest risk systems myself: live state performance, deferred deep linking, and the CI/CD release pipeline.
Functionally, the app lets users join groups, pick odds on upcoming matches (1X2, over/under), and track a running ticket score that updates live as scores change backed by group leaderboards and a full contextual onboarding flow, across multiple European leagues.
![]()
![]()
![]()
Tech Stack
- Frontend: React Native, Expo, TypeScript, Redux (normalized store), Native plugins
- Tooling: Node.js (Google Sheets translation sync), Google Sheets API
- Infrastructure: GitHub Actions CI/CD, Expo Workflow, App Store Connect, Google Play Console
Key Features
Normalized Redux store for live lists. The app is dense with live updating lists, a known performance trap in React Native's old architecture, where a single unoptimized list could lag the whole experience. I normalized the store so data lives as objects keyed by ID rather than arrays, and gave each list item a memoized selector subscribed only to its own ID. Updating one item now rerenders only that item, never the whole collection kept scrolling smooth while live match data continuously updated on mid range Android.
Deferred deep linking (link + data through store install). Anyone who's built this knows how painful it is. I got deferred deep links to preserve both the link and its payload through the App Store / Play Store install flow, so a shared prediction survives a brand new install and drops the user exactly where the link intended, turned shared content into a measurable new user acquisition channel.
CI/CD release pipeline. Pushing a Git tag triggers GitHub Actions to build both the iOS and Android binaries and submit them to App Store Connect and Google Play, collapsing a multi step manual release into a single tag and removing all manual build steps.
Two-tier onboarding system. A contextual tooltip system that doubles as both first run tutorial and persistent in app guide. Each step is an object carrying a component name, tooltip text, and an onClose side effect (navigate, dispatch mock odds, etc.). Progress is persisted per user ID in Redux, so it never replays and resumes correctly even if the app is killed mid tutorial.
Google Sheets translation pipeline. Multi language copy needed constant updates from non developers, and hand syncing JSON locale files was error prone. I wrote a Node script that authenticates to Google Sheets via a service account, reads each row (translation key + one column per language), and writes one JSON file per language into assets/_locales/. The copy team now owns all app text directly with zero developer involvement for text changes.
Shareable link web previews. Every shared link renders a lightweight web template pulling live data from our API, so people without the app see real content plus a strong install CTA, bridging non app users into the install funnel.
Results & Impact
Shipped and live on both the App Store and Google Play, spanning multiple European leagues. The normalized state architecture delivered smooth scrolling through continuously updating live match data even on mid range devices, and deferred deep linking turned shared links into a measurable new user acquisition channel. I took the project from an empty repo to two shipped store listings while leading 3 engineers over ~13 months.