Overview

When building real-time multiplayer web applications, supporting mobile users seamlessly is one of the most critical challenges. For Bilgo, our interactive trivia and competitive learning platform, we recently bridged the gap between our native Android app and our React + TypeScript web client.

While the Android version is currently in the Google Play review pipeline, we rolled out a standalone, signed APK distribution channel coupled with full cross-platform synchronization.

Here is a breakdown of the architectural challenges we solved and how we structured the solution.

  1. The Challenge: Divergent Schemas Across Platforms

During the early stages of development, the Android client and the web frontend stored gameplay progress slightly differently in Cloud Firestore:

Web Client: Stored achievements as key-value maps (achievements: { [id]: { unlocked: boolean, progress: number } }).
Android Client: Persisted achievements as an array of unique identifier strings (unlockedAchievements: ["first_win", "streak_3", ...]).
Streak Telemetry: The mobile app stored streak metadata inside nested objects (streak: { count: number, best: number }), while web aggregations previously expected flat counters.

As a result, mobile players who accumulated significant streaks saw their count display as zero on the web leaderboard, and unlocked mobile medals did not register on the web profile.

  1. The Solution: Unified Ingestion and Non-Destructive Merging

Instead of forcing a destructive migration on active player databases, we introduced a resilient aggregation pipeline on the web client:

Multi-Source Streak Extraction: A normalized extraction utility inspects all candidate structures (streak.count, streak.best, streakCount, and stats.bestStreak) and returns the true mathematical maximum across data sources.
Non-Destructive Document Merging: When fetching global and weekly leaderboards across Firestore instances, documents from publicProfiles and users collections are merged symmetrically using Math.max across scores, wins, XP, and streak counts.
Dual-Write Achievement Unlocks: When an achievement unlocks on the web, we invoke arrayUnion to append the achievement ID to unlockedAchievements while concurrently recording the structured map. This ensures future mobile sessions immediately recognize the unlocked badge.

  1. Real-Time Download Telemetry

To measure user adoption prior to the official Google Play rollout, we implemented an in-house telemetry pipeline:

Environment Detection: Client-side detection identifies OS (Android, Windows, iOS, macOS) and device category (mobile, tablet, desktop).
Event Logging: Each APK download registers an atomic increment and writes an event log entry inside Firestore, preserving audit trails without requiring external third-party tracking scripts.
Real-Time Admin Panel: An administrative dashboard listens via onSnapshot to display real-time counters for total downloads, unique devices, and registered active mobile players.
Tech Stack Summary
Frontend: React 18, TypeScript, Tailwind CSS, Vite
Backend & Database: Google Cloud Firestore, Firebase Modular SDK (v10)
Mobile: Native Android APK distribution
Hosting: Netlify Edge
Check It Out
Web Application: https://bilgo.netlify.app
Android Download Hub: https://bilgo.netlify.app/download

Developed by the team at PixelGroup. Feedback and technical discussions are always welcome!