Skip to main content

Overview

d-sports-engage-native (package name: engage-native, version 1.10.0) is the native mobile app for D-Sports. It mirrors the core PWA experience on iOS and Android: wallet, shop, leaderboard, locker room, and profile. The app targets both native and web (responsive) and uses the same backend (d-sports-api) as the PWA for API and checkout flows.

Tech stack

CategoryTechnology
FrameworkExpo 54, React Native 0.81, React 19
AuthClerk (Expo)
PaymentsRevenueCat (react-native-purchases)
Web3Thirdweb
StateZustand
StorageMMKV
UILucide React Native
NavigationExpo Router 6
AnimationsReanimated 4
PackageBun

Features

  • Wallet — Tokens, holdings, pack opening, crypto checkout (via PWA backend)
  • Shop — Collectibles, cart, coin bundles, crypto checkout via Thirdweb
  • Leaderboard — Rankings and filters
  • Locker room — Social feed, quests, daily games (Pick ‘Em, Spin Wheel, Guess the Player)
  • Profile — User profile, stats, and settings
  • Onboarding — New user flow with team selection
  • Theme — Dark/light mode (default dark)

Project structure

app/
├── (auth)/              # Login, signup, SSO callback, password reset
├── (onboarding)/        # New user onboarding flow
├── (tabs)/              # Main tab navigation (wallet, shop, leaderboard, locker room, profile)
├── settings/            # Settings pages with nested modals/tabs
└── _layout.tsx          # Root layout with providers and auth protection

components/
├── wallet/              # Wallet sub-components (TokenRow, ActionModal, PackOpeningModal, etc.)
├── shop/                # Shop sub-components (CartModal, CryptoCheckoutModal, etc.)
├── locker-room/         # Feed, quests, daily games, explore teams/fans
├── leaderboard/         # BaseLeaderboard, LeaderboardModal
├── settings/            # Setting items, sections, and modal tabs
├── ui/                  # Reusable primitives (Button, TextField, TutorialOverlay, etc.)
├── layout/              # AppScreen wrapper (responsive web max-width)
└── Icon/                # Icon wrapper using lucide-react-native

hooks/                   # Screen-level hooks (use-wallet-screen, use-shop-screen, etc.)
lib/api/                 # API client modules (wallet, shop, user, quests, checkout, etc.)
context/                 # React Context (auth/user, collectibles, navbar visibility)
types/                   # Shared TypeScript types (wallet, shop, checkout, API)
constants/               # Static data and configuration
theme/                   # Brand colors, spacing, typography tokens
services/                # Zustand store, MMKV storage adapter

Getting started

1

Install dependencies

Clone the repository and install with Bun:
bun install
2

Configure environment

The app uses EXPO_PUBLIC_* environment variables. Create a .env file at the repo root with:
VariablePurpose
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEYClerk authentication
EXPO_PUBLIC_API_URLBackend API base URL (defaults to https://api.d-sports.org)
EXPO_PUBLIC_TW_CLIENT_IDThirdweb client ID for web3
EXPO_PUBLIC_REVENUECAT_API_KEYRevenueCat in-app purchases
EXPO_PUBLIC_REVENUECAT_APPSTORE_IDRevenueCat App Store ID
EXPO_PUBLIC_REVENUECAT_ENTITLEMENTRevenueCat entitlement name
EXPO_PUBLIC_SUPABASE_URLSupabase project URL
EXPO_PUBLIC_SUPABASE_KEYSupabase publishable key
3

Start the dev server

bunx expo start
Press a for Android, i for iOS, or scan the QR code with Expo Go.

EAS builds

The app uses Expo Application Services (EAS) for native builds and OTA updates.
  • Project: @d-sports-apps/d-sports-engage
  • EAS dashboard: expo.dev
# Development builds (includes expo-dev-client)
bun run build:dev           # Both platforms
bun run build:dev:ios       # iOS simulator only
bun run build:dev:android   # Android APK only

# Start dev server for dev builds
bunx expo start --dev-client
iOS dev builds target the simulator by default. For a physical device, run eas build --profile development-device --platform ios.

Architecture

The codebase follows a modular architecture where screen files are thin render shells — all state, effects, and handlers live in dedicated hooks.
PatternDescription
Screen filesJSX only — import a hook and render
Custom hooksOne per screen or feature (use-wallet-screen.ts, use-shop-screen.ts)
External stylesheetsAll StyleSheet.create() calls live in styles/ subdirectories
Barrel exportsEach component domain has an index.ts for clean imports
API client layerlib/api/client.ts provides authenticated requests via Clerk tokens with MMKV cache fallback
Path alias@/* maps to the project root

API client

All backend calls go through lib/api/client.ts, which automatically attaches Clerk auth tokens. The client handles both normalized ({ success, data, error, code }) and legacy response formats from d-sports-api. Individual domain modules (wallet-api.ts, shop-api.ts, leaderboard-api.ts, etc.) wrap the base client with typed endpoint helpers.

State management

  • Zustand + MMKV for global state with synchronous persistence (theme, cart, points)
  • React Context for auth/user profile, collectibles, and navbar visibility
  • RevenueCat provider for in-app purchase entitlements

Ecosystem overview

See how the native app fits with the PWA, site, and Mic’d Up.