Overview
d-sports-engage-native (package name: engage-native) 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 also supports web via responsive layout and PWA manifest.
Tech stack
Category Technology Framework Expo 54, React Native 0.81, React 19 Language TypeScript 5.9 Auth Clerk (Expo) Payments RevenueCat (react-native-purchases) Web3 Thirdweb State Zustand 5 Storage MMKV Animation Reanimated 4.1 UI icons Lucide React Native Navigation Expo Router 6 (file-based routing) Package Bun
Features
Wallet — tokens, holdings, pack opening, crypto checkout (via PWA backend and Thirdweb SDK)
Shop — collectibles, cart, coin bundles, crypto checkout
Leaderboard — rankings, filters, and season-based views
Locker room — social feed, posts, quests, daily games (Pick’Em, Spin Wheel, Guess the Player), team exploration, and fan profiles
Profile — user profile, stats, and full settings suite
Onboarding — new-user onboarding flow with team selection
Theme — dark/light mode (default dark)
Project structure
The codebase follows a modular architecture pattern — screen files are thin render shells containing only JSX, with all business logic extracted into dedicated hooks.
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/ # Locker room components (FeedSection, DailyPickEmGame, QuestSection, etc.)
├── leaderboard/ # BaseLeaderboard, LeaderboardModal
├── settings/ # SettingItem, SettingSection, and modals/tabs
├── ui/ # Reusable primitives (Button, TextField, TutorialOverlay, etc.)
├── Icon/ # Icon wrapper using lucide-react-native
└── theme-provider.tsx
hooks/
├── use-wallet-screen.ts # All wallet state, effects, and handlers
├── use-shop-screen.ts # All shop state, effects, and handlers
├── use-feed-section.ts # Feed posts state and handlers
├── use-carousel-scroll.ts # Carousel scroll logic
└── use-draggable-scroll.ts # Drag-to-scroll logic
lib/api/ # API client modules (wallet, shop, user, quests, checkout, etc.)
context/ # React Context (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
Key architecture patterns
File-based routing via Expo Router with route groups (tabs), (auth), (onboarding)
Thin screens — screen files import a hook and render JSX; all state and logic live in hooks/
External stylesheets — StyleSheet.create() is never inline; styles live in styles/ directories
Barrel exports — each component domain has an index.ts re-exporting all public components
API client layer in lib/api/ with MMKV cache fallback (lib/api/cache.ts)
Path alias @/* maps to the project root
Getting started
Clone and install
git clone < repo-ur l >
cd d-sports-engage-native
bun install
Configure environment
Create a .env file with the required variables: Variable Purpose EXPO_PUBLIC_CLERK_PUBLISHABLE_KEYClerk authentication EXPO_PUBLIC_API_URLBackend API base URL EXPO_PUBLIC_TW_CLIENT_IDThirdweb Web3 client ID EXPO_PUBLIC_REVENUECAT_API_KEYRevenueCat in-app purchases EXPO_PUBLIC_REVENUECAT_APPSTORE_IDRevenueCat App Store ID EXPO_PUBLIC_REVENUECAT_ENTITLEMENTRevenueCat entitlement identifier EXPO_PUBLIC_SUPABASE_URLSupabase client URL EXPO_PUBLIC_SUPABASE_KEYSupabase publishable key
Only EXPO_PUBLIC_* variables are accessible at runtime in the Expo app.
Start the dev server
Press a for Android, i for iOS, or scan the QR code with Expo Go.
Development builds (optional)
For a full dev-client build with native module support: bun run build:dev:ios # iOS simulator
bun run build:dev:android # Android APK
After installing the dev build, start the server with: bunx expo start --dev-client
EAS builds and deployments
The app uses Expo Application Services (EAS) for native builds, OTA updates, and store submissions.
Build profile Command Purpose Development bun run build:devDev builds with dev-client and fast refresh Preview bun run build:previewRelease-mode builds for internal QA Production bun run build:prodStore-ready builds with auto-incrementing version
OTA updates
Push JavaScript and asset changes to existing installs without a new store build:
bun run update --branch production --message "Fix: wallet balance display"
Build profile Update channel Recipients developmentdevelopmentDev builds previewpreviewInternal testers productionproductionApp store users
OTA updates only work if the JS is compatible with the installed native binary. If you add or change native modules, you must do a full build first and bump version in app.json.
API normalization (Phase 2)
The app is migrating to a standard response envelope for all backend communication:
// Success
{ success : true , data : T }
// Error
{ success : false , error : string , code ?: string }
The API client in lib/api/client.ts handles response normalization. As backend routes are migrated, the client will be simplified to remove legacy response-shape detection. See the Phase 2 plan in the repo at docs/plans/PHASE-2-API-NORMALIZATION.md for the full migration status and execution plan.
Ecosystem overview See how the native app fits with the PWA, site, and Mic’d Up.