Back to projects

Blackjack Legend

Fully-featured mobile blackjack game for iOS and Android. Local-first React Native app (Expo SDK 54, Zustand, Reanimated) with a Firebase backend for Google and Apple sign-in, cloud save with debounced conflict-safe writes, and a global leaderboard. Currently in TestFlight with five testers.

React Native 0.81 Expo SDK 54 TypeScript Zustand React Navigation Reanimated Firebase Firestore AsyncStorage EAS Build

The Idea

Blackjack Legend is a native iOS and Android blackjack game built to be a real shipped product, not a coding exercise. The goal was to handle the full arc: a correct blackjack engine, a mobile-first UX with animation and haptics, authentication with Google and Apple, cloud-synced progress across devices, and a global leaderboard, all wrapped in an EAS build pipeline that can actually push to the App Store.

The game ships with progression and engagement systems on top of the base ruleset: 8 unlock-gated tables, an 8-rank XP system, 18 achievements across three categories, seeded daily challenges, and a 7-day login streak reward cycle. The engagement layer is what turns "I wrote a blackjack engine" into "people open the app again tomorrow".

Tech Stack

LayerTechnologyPurpose
FrameworkReact Native 0.81 + Expo SDK 54Cross-platform iOS and Android from one TS codebase
LanguageTypeScript 5.9End-to-end types including Firestore documents
StateZustand 5Game state, auth, and engagement systems
NavigationReact Navigation 7Bottom tabs plus native stack
AnimationReanimated 4 + SVGCard deal, chip drag, radar chart
Authexpo-auth-session, expo-apple-authenticationGoogle OAuth 2.0 (PKCE) and native Apple Sign-In
BackendFirebase (Auth + Firestore) + AnalyticsUser accounts, cloud save, leaderboard, events
Local storageAsyncStorageSource-of-truth for all game state on device
Audio + hapticsexpo-audio, expo-haptics, expo-blurSound effects, tactile feedback, blur UI
BuildEAS Build + EAS SubmitCloud builds and automated store submission

Architecture Decisions

  • Local-first with an AsyncStorage source of truth. The game is fully playable offline. Firestore is a sync target, not the authoritative state, which keeps the game responsive and removes network latency from the hot path.
  • Zustand instead of Redux. A single-screen game with a handful of stores (game, auth, engagement, settings) does not need Redux ceremony. Zustand stores keep the code close to the state they manage.
  • Firebase for the backend instead of a custom API. The features this app actually needs (OAuth, per-user documents, a top-100 leaderboard query, analytics) are exactly what Firebase Auth plus Firestore give you out of the box. Standing up a Django or Node service would have been weeks of work for a strictly worse product.
  • Expo Managed with EAS Build. EAS removes the usual iOS signing and Android Gradle tax, and EAS Submit pushes straight to App Store Connect and the Play Console. That is what made TestFlight achievable as a solo developer.
  • Reanimated 4 for the card deal animation and chip drag. UI-thread animations keep 60 fps during gameplay even when the JS thread is doing basic-strategy math.

Cloud Sync and Conflict Resolution

The interesting engineering problem in the app is not the blackjack math. It is reconciling local game state with the cloud in a way that never causes a player to lose progress, even across offline play, reinstalls, and multi-device usage.

  • Writes are debounced by 3 seconds. Back-to-back state changes (hands, XP ticks, balance updates) coalesce into a single Firestore write instead of hammering the network.
  • Reads are conflict-gated. On sign-in, the cloud document only replaces local state if the cloud XP is strictly greater than local XP. That rule prevents a fresh install on a new device from wiping out progress that has not yet been synced from the other device.
  • Leaderboard writes are separate from the full save. The top-100-by-balance query reads a compact per-user record so the leaderboard stays cheap even as the full save grows.
  • Guest mode is supported. A player who does not sign in still gets full gameplay, saved locally. Signing in later promotes the guest state to a cloud-backed account.

Authentication

Sign-in goes through expo-auth-session for Google (OAuth 2.0 with PKCE) and expo-apple-authentication for native Apple Sign-In. expo-crypto generates a secure nonce for the Apple flow so the identity token can be verified against the request.

Neither provider stores anything the app does not need. The user-facing account only exposes a display name and avatar; everything else is derived from Firestore documents that the user owns.

Gameplay Engine

  • Full blackjack rules: hit, stand, double down, split up to 4 hands, insurance on dealer ace, auto-stand on 21, split-aces restricted to one card.
  • Table-dependent variants: Soft 17 vs Hit 17 dealer rule, blackjack pays 1.5x or 1.2x, different deck counts from 1 to 8.
  • Basic strategy tracker: every player decision is validated against the basic-strategy chart for the current table, and the accuracy percentage feeds the stats dashboard and achievements.
  • Auto-play mode that runs basic strategy end-to-end, useful for QA and for players who want to watch optimal play.
  • Two betting input modes: a chip tray for taps and a drag mode that lets the player physically drop chips onto the bet circle.

Progression and Engagement

The engagement layer on top of the engine:

  • 8 unlock-gated tables from Starter ($5 to $100 bets) to Legend ($1k to $50k bets), gated by rank plus a total-wager threshold.
  • 8-rank XP system (Newcomer to Legend) with a chip reward at each rank up. Base 10 XP per hand, +15 for a win, +25 for a blackjack.
  • 18 achievements across Milestone, Skill, and Style categories with chip rewards from 25 to 2,000.
  • Three seeded daily challenges per day across easy, medium, and hard difficulty, covering hands played, wins, blackjacks, doubles, strategy matches, and wagers.
  • 7-day repeating login streak: 50, 75, 100, 150, 200, 300, 500 chips, resets on a missed day.
  • Stats dashboard with a 6-axis radar chart profiling Skill, Aggression, Risk, Luck, Profit, and Experience, which resolves to one of eight play-style archetypes.

Status

Currently in TestFlight with 5 testers. The full game loop, cloud sync, leaderboard, and engagement systems are live in the test build. The repository is private while the app works its way toward a public App Store and Play Store release.