Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 75 additions & 36 deletions repositories/d-sports-engage-native.mdx
Original file line number Diff line number Diff line change
@@ -1,56 +1,71 @@
---
title: "d-sports-engage-native"
description: "Native iOS and Android app for D-Sports Engage. Expo 54, React Native, Clerk, RevenueCat, Thirdweb."
description: "Native iOS and Android app for D-Sports Engage. Expo 55, React Native 0.83, Clerk, RevenueCat, Thirdweb."
icon: "smartphone"
---

## 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.
**d-sports-engage-native** (package name: `engage-native`, version **1.18.1**) 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.

- **Run:** `bunx expo start` or `bun run start` — then press `a` for Android or `i` for iOS, or scan the QR code with Expo Go.
- **Run:** `bunx expo start` — then press `a` for Android or `i` for iOS, or scan the QR code with Expo Go.
- **TypeScript check:** `bun tsc --noEmit`

## Tech stack

| Category | Technology |
| ---------- | ------------------------- |
| Framework | Expo 54, React Native 0.81, React 19 |
| Auth | Clerk (Expo) |
| Payments | RevenueCat (react-native-purchases) |
| Web3 | Thirdweb |
| State | Zustand |
| Storage | MMKV |
| UI | Lucide React Native |
| Navigation | Expo Router |
| Package | Bun |
| Category | Technology |
| ------------- | ----------------------------------------------- |
| Framework | Expo 55, React Native 0.83.4, React 19.2 |
| Auth | Clerk (`@clerk/clerk-expo`) |
| Payments | RevenueCat (`react-native-purchases`) |
| Web3 | Thirdweb SDK |
| State | Zustand 5 + MMKV persistence |
| Navigation | Expo Router 55 (file-based, typed routes) |
| Push | OneSignal (`react-native-onesignal`) |
| Monitoring | Sentry (`@sentry/react-native`) |
| Analytics | Vercel Analytics |
| UI | Lucide React Native |
| Animations | React Native Reanimated 4 |
| Package | Bun |

## Features

- **Wallet** — Tokens, holdings, pack opening, crypto checkout (via PWA backend)
- **Shop** — Collectibles, cart, coin bundles, checkout
- **Leaderboard** — Rankings and filters
- **Locker room** — Social feed and engagement
- **Profile** — User profile and settings
- **Theme** — Dark/light mode (default dark)

## What changed since last docs sync

- Team-aware experiences were expanded to align with backend team/favorites behavior.
- Quest and rewards surfaces were updated to support per-team progression and pass-aware eligibility.
- Pack opening and odds disclosure UX were upgraded with safer interactions and clearer status/error handling.
- Settings and account flows were expanded, including in-app account deletion and richer support/data controls.
- **Wallet** — token balances, holdings, pack opening, crypto checkout (Thirdweb + PWA backend)
- **Shop** — collectibles, 3D model viewer, cart, coin bundles, RevenueCat + crypto checkout
- **Leaderboard** — team-scoped rankings, quest hero icons, per-team quest sections
- **Locker room** — social feed, daily pick'em, spin wheel, guess the player, explore fans/teams
- **Profile** — achievement badges, milestone avatars, follow lists, points history
- **Settings** — account management, accessibility, appearance, notifications, support, changelog
- **Widgets** — iOS home screen and Live Activity widgets, Android home screen widget
- **Theme** — dark/light mode (default dark)

## Environment variables

The app uses `EXPO_PUBLIC_*` prefixed variables accessible at runtime:

| Variable | Purpose |
| -------- | ------- |
| `EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk authentication |
| `EXPO_PUBLIC_API_URL` | Backend API base URL |
| `EXPO_PUBLIC_TW_CLIENT_ID` | Thirdweb client ID |
| `EXPO_PUBLIC_REVENUECAT_API_KEY` | RevenueCat API key |
| `EXPO_PUBLIC_REVENUECAT_APPSTORE_ID` | RevenueCat App Store ID |
| `EXPO_PUBLIC_REVENUECAT_ENTITLEMENT` | RevenueCat entitlement ID |
| `EXPO_PUBLIC_SUPABASE_URL` | Supabase project URL |
| `EXPO_PUBLIC_SUPABASE_KEY` | Supabase publishable key |

## Backend integration surfaces

- Primary API source: `d-sports-api` under `/api/*`.
- Native app consumes team, league, quest, reward, wallet, commerce, and social endpoints.
- Retry/caching logic and auth token injection are centralized in app API client modules.
- Retry/caching logic and auth token injection are centralized in `lib/api/client.ts` with MMKV cache fallback.
- Crypto checkout calls the PWA backend (`POST /api/checkout/crypto` and `/api/checkout/crypto/verify`), then signs on-chain via Thirdweb.

## Quest and pass UX integration

- Quest UI now reflects team-scoped eligibility and pass-gated progression where applicable.
- Quest UI reflects team-scoped eligibility and pass-gated progression where applicable.
- Reward presentation differentiates free/unpaid states and claimability.
- Native progression state is expected to mirror backend eligibility and completion semantics.
- Native progression state mirrors backend eligibility and completion semantics.

## Team-aware experiences

Expand All @@ -64,12 +79,36 @@ icon: "smartphone"

## Getting started

1. Clone the repository and run `bun install`.
2. Configure environment (Clerk, RevenueCat, Thirdweb, API base URL) per repo README.
3. Run `bunx expo start`.
4. For development builds: `bun run build:dev` (EAS) or run with Expo dev client.

The app targets both native and web (responsive) and uses the same backend (d-sports-api) as the PWA for API and checkout flows.
<Steps>
<Step title="Install dependencies">
```bash
bun install
```
</Step>
<Step title="Configure environment">
Copy `.env` and set your `EXPO_PUBLIC_*` keys for Clerk, RevenueCat, Thirdweb, and the API base URL.
</Step>
<Step title="Start the dev server">
```bash
bunx expo start
```
Press `a` for Android, `i` for iOS, or scan the QR code with Expo Go.
</Step>
<Step title="Build for devices (optional)">
```bash
# Development build (all platforms)
bun run build:dev

# Preview build (iOS only)
bun run build:preview:ios

# Production build with App Store submission
bun run build:submit:ios
```
</Step>
</Steps>

The app targets both native and web (responsive) and uses the same backend (`d-sports-api`) as the PWA for API and checkout flows.

## Deep dives

Expand Down
107 changes: 92 additions & 15 deletions repositories/d-sports-engage-native/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,105 @@ title: "Native architecture"
description: "Architecture overview for d-sports-engage-native application layers and platform behavior."
---

## App architecture
## Project structure

The native app is structured around Expo Router screens, feature-oriented components, shared hooks, and API modules.
```text
app/
├── (auth)/ # Login/signup screens
├── (onboarding)/ # New user onboarding flow
├── (tabs)/ # Main tab navigation
│ ├── wallet.tsx # Wallet screen (JSX only — logic in hook)
│ ├── shop.tsx # Shop screen (JSX only — logic in hook)
│ ├── leaderboard/ # Leaderboard screens
│ ├── locker-room/ # Social feed
│ └── profile.tsx # User profile
├── settings/ # Settings pages with nested modals/tabs
└── _layout.tsx # Root layout with providers + auth protection

- Routing: `app/*` with grouped routes for tabs/auth/onboarding/settings.
- Feature logic: extracted hooks for wallet, shop, locker room, and settings.
- Shared contexts: user, collectibles, accessibility, and UI visibility/state controls.
components/
├── wallet/ # Extracted wallet sub-components
├── shop/ # Extracted shop sub-components
├── locker-room/ # Locker room components
├── leaderboard/ # Leaderboard components
├── profile/ # Profile components
├── settings/ # Settings components
├── navigation/ # PillTabBar, tab config
├── layout/ # AppScreen wrapper (responsive web max-width)
├── ui/ # Reusable UI primitives
├── Icon/ # Icon wrapper (lucide-react-native)
└── theme-provider.tsx # Theme context (dark/light)

## State and context boundaries
hooks/ # Feature hooks (use-wallet-screen, use-shop-screen, etc.)
lib/api/ # API client modules with MMKV cache fallback
context/ # React Context providers (user, collectibles, navbar)
services/ # Zustand store, MMKV storage, types
theme/ # Brand colors, design tokens
types/ # Shared TypeScript types
constants/ # Shared constants
```

- Local/ephemeral UI state lives near feature hooks and components.
- Cross-screen state is managed with context providers and persisted storage where required.
- User/session-sensitive state is coordinated with backend auth and profile sync endpoints.
## Routing

## API client and retry behavior
The app uses **Expo Router** with file-based routing and typed routes enabled.

- **Route groups:** `(tabs)` for main navigation, `(auth)` for login/signup, `(onboarding)` for new users
- **Settings:** `settings/` directory contains settings pages with nested components, modals, and tabs
- **Auth protection:** `_layout.tsx` automatically redirects based on authentication and onboarding state
- **Path alias:** `@/*` maps to the project root

## Screen pattern

Screen files contain **only imports and JSX**. All state, effects, and handlers live in dedicated hooks:

- `hooks/use-wallet-screen.ts` — wallet state, token fetch effects, PIN verification, transaction handlers
- `hooks/use-shop-screen.ts` — cart state, product queries, carousel auto-scroll, checkout logic
- `hooks/use-feed-section.ts` — locker room feed logic

Sub-components are extracted into `components/wallet/`, `components/shop/`, etc. with barrel exports via `index.ts`.

## Tab bar

The tab bar implementation differs by platform:

- **iOS:** uses `NativeTabs` from `expo-router/unstable-native-tabs` (system UIKit tab bar) with `systemChromeMaterialDark` material and gold selection accent (`#FFD700`).
- **Android + web:** uses a custom JS `PillTabBar` overlay with `expo-blur` (`BlurView`). The default system tab bar is hidden.
- **Shared config:** `components/navigation/tab-config.ts` defines tab order, SF Symbol pairs for iOS, and active-tab resolution logic.

## State management

| Layer | Technology | Location |
| ----- | ---------- | -------- |
| Global store | Zustand 5 + MMKV persistence | `services/store.ts`, `services/storage.ts` |
| Auth and user | React Context | `context/user-context.tsx` |
| Collectibles | React Context | `context/collectibles-context.tsx` |
| Navbar visibility | React Context | `context/navbar-visibility-context.tsx` |
| Local/ephemeral | Component state in hooks | `hooks/use-*-screen.ts` |

## API client and caching

- All network calls route through `lib/api/*` modules.
- Client wrappers handle auth token propagation, error normalization, and retry strategy.
- Quest/reward/team flows should consume backend eligibility as source of truth.
- `lib/api/client.ts` handles auth token injection (Clerk), error normalization, and retry strategy.
- `lib/api/cache.ts` provides `fetchWithCache()` with MMKV cache-first fetching.
- Domain modules: `wallet-api.ts`, `shop-api.ts`, `user-api.ts`, `quests-api.ts`, `leaderboard-api.ts`, `locker-room-api.ts`, `teams-api.ts`, `collectibles-api.ts`, `checkout-api.ts`, `games-api.ts`.

## Checkout and payments

| Method | Technology | Details |
| ------ | ---------- | ------- |
| Fiat (Apple IAP, Google Play, Stripe) | RevenueCat | `lib/revenuecat/provider.tsx` |
| Crypto (on-chain) | Thirdweb SDK | `lib/api/checkout-api.ts` calls `POST /api/checkout/crypto`, Thirdweb signs the transaction |

Supported chains for crypto checkout: **Arbitrum** (default), Ethereum, Polygon.

## Platform-specific behavior

- iOS/Android platform differences are handled in native-specific components and runtime checks.
- Web-target support exists but mobile behavior is primary for interaction and performance design.
- Haptics, modal controls, and animation handling are implemented with platform-safe fallbacks.
- **iOS/Android:** platform differences are handled in native-specific layout files (e.g., `_layout.ios.tsx` vs `_layout.android.tsx`) and runtime checks.
- **Web:** responsive desktop layout via `AppScreen` wrapper (`maxWidth: 480px`), web hover states (`WebHoverWrapper`), PWA manifest with `display: standalone`.
- **Haptics:** `expo-haptics` with platform-safe fallbacks.
- **Animations:** React Native Reanimated 4 for scroll-based navbar hide/show and UI transitions.

## Widgets

- **iOS:** `RankOrPointsWidget` (small/medium) and `LiveStatusActivity` (Live Activity for score updates) via `expo-widgets`.
- **Android:** `RankOrPointsWidget` via `react-native-android-widget`, refreshes every 30 minutes.
- Widget data is prepared in `lib/widget-data.ts`.