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
96 changes: 63 additions & 33 deletions repositories/d-sports-engage-native.mdx
Original file line number Diff line number Diff line change
@@ -1,56 +1,54 @@
---
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.

## 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, React 19.2 |
| Auth | Clerk Expo (`@clerk/clerk-expo` 2.19) |
| Payments | RevenueCat (`react-native-purchases` 9.10) |
| Web3 | Thirdweb 5.118 |
| State | Zustand 5.0 |
| Storage | MMKV 4.1 |
| UI | Lucide React Native 0.562 |
| Navigation | Expo Router 55 |
| Push | OneSignal (`react-native-onesignal` 5.4) |
| Monitoring | Sentry (`@sentry/react-native` 8.x) |
| Realtime | Supabase (`@supabase/supabase-js` 2.x) |
| 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
- **Shop** — Collectibles, cart, coin bundles, fiat (RevenueCat) and crypto (Thirdweb) checkout
- **Leaderboard** — Rankings, team-scoped views, and quest hero icons
- **Locker room** — Social feed, daily pick'em, spin wheel, guess-the-player games
- **Profile** — User profile, milestone avatars, achievement badges, follow lists
- **Settings** — Account management, accessibility, appearance, notifications, in-app support
- **Widgets** — iOS home screen widgets (rank/points) and Live Activities, Android widgets
- **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.

## 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 in `lib/api/cache.ts`.

## 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 +62,44 @@ 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">
Create a `.env` file at the repo root with these `EXPO_PUBLIC_*` keys:

| Variable | Description |
| -------- | ----------- |
| `EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk publishable key |
| `EXPO_PUBLIC_API_URL` | Backend API base URL (e.g. `https://api.d-sports.org`) |
| `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 identifier |
| `EXPO_PUBLIC_SUPABASE_URL` | Supabase project URL |
| `EXPO_PUBLIC_SUPABASE_KEY` | Supabase publishable (anon) key |
</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="EAS builds (optional)">
For native development builds:
```bash
bun run build:dev:ios # iOS simulator
bun run build:dev:android # Android internal
bun run build:preview # Internal distribution (both platforms)
bun run build:prod # Production (both platforms)
```
</Step>
</Steps>

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

## Deep dives

Expand Down
55 changes: 44 additions & 11 deletions repositories/d-sports-engage-native/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,59 @@ description: "Architecture overview for d-sports-engage-native application layer

## App architecture

The native app is structured around Expo Router screens, feature-oriented components, shared hooks, and API modules.
The native app is structured around Expo Router file-based routing, feature-oriented components, shared hooks, and API modules.

- 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.
```
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 and tabs
└── _layout.tsx # Root layout with provider hierarchy and auth protection
```

- **Routing:** `app/*` with grouped routes for `(tabs)`, `(auth)`, `(onboarding)`, and `settings/`. Typed routes are enabled via `experiments.typedRoutes`.
- **Screen pattern:** Screen files contain only JSX. All state, effects, and handlers live in dedicated hooks (e.g. `hooks/use-wallet-screen.ts`, `hooks/use-shop-screen.ts`).
- **Feature components:** Extracted into domain directories — `components/wallet/`, `components/shop/`, `components/locker-room/`, `components/leaderboard/`, `components/profile/`, `components/settings/`.
- **Shared contexts:** `UserContext` (auth and profile), `CollectiblesContext` (owned packs/items), `AccessibilityContext`, `NavBarVisibilityContext`, `CreateActionContext`.

## Tab bar

The tab bar uses platform-specific implementations:

- **iOS:** `app/(tabs)/_layout.ios.tsx` uses `NativeTabs` from `expo-router/unstable-native-tabs` for the system UIKit tab bar. The wallet tab shows a numeric badge for unopened packs.
- **Android and web:** `app/(tabs)/_layout.tsx` uses a custom `PillTabBar` overlay with `expo-blur` on Android.
- **Shared config:** `components/navigation/tab-config.ts` defines tab order, SF Symbol pairs for iOS, and active-tab detection logic.

## State and context boundaries

- **Zustand** (`services/store.ts`) with MMKV persistence (`services/storage.ts`) for global state (theme, cart, points).
- **React Context** providers in `context/` for auth, collectibles, navbar visibility, and action modal state.
- 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.

## API client and retry behavior

- 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.
- All network calls route through `lib/api/*` modules with a centralized client in `lib/api/client.ts`.
- The client handles auth token injection (via Clerk), error normalization, and retry strategy.
- `lib/api/cache.ts` provides `fetchWithCache()` for MMKV cache-first fetching.
- Domain API 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

- **RevenueCat** (`lib/revenuecat/provider.tsx`) handles fiat payments: Apple IAP (native), Google Play (native), Stripe (web).
- **Crypto checkout** (`lib/api/checkout-api.ts`) calls the PWA backend at `POST /api/checkout/crypto` and `POST /api/checkout/crypto/verify`.
- **Thirdweb SDK** provides on-chain transaction signing. Supported chains: 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 via platform-specific file extensions (e.g. `_layout.ios.tsx`, `_layout.android.tsx`).
- **Haptics:** `hooks/use-haptics.ts` with platform-safe fallbacks.
- **Animations:** React Native Reanimated 4.x for scroll-based navbar visibility and UI transitions.
- Web-target support exists with responsive `maxWidth: 480px` container (`components/layout/AppScreen.tsx`), hover states, and PWA manifest.

## Widgets

- **iOS:** Home screen widgets (`RankOrPointsWidget`) and Live Activities (`LiveActivityStatus`) via `expo-widgets`.
- **Android:** Home screen widgets via `react-native-android-widget` with a `RankOrPointsWidget`.
- Widget data is managed in `lib/widget-data.ts` with controls in `widgets/widget-controls.ts`.
30 changes: 30 additions & 0 deletions repositories/d-sports-engage-native/feature-mapping.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,45 @@ description: "Native feature coverage and parity mapping against backend/PWA beh
- Wallet screens consume balances, token data, and secure key/pin flows from backend APIs.
- Pack browsing, purchase, and open flows use backend-driven states and inventory refresh behavior.
- Odds-disclosure surfaces read backend-provided probability payloads.
- Crypto checkout supports Arbitrum, Ethereum, and Polygon chains via Thirdweb SDK.
- Fiat checkout uses RevenueCat for Apple IAP, Google Play, and Stripe (web).

## Quest, rewards, and pass surfaces

- Quest UI supports team-aware progression and pass-gated eligibility.
- Reward states and claim flows follow backend quest/reward APIs.
- Global pass and event pass effects are reflected in native quest visibility/completion UX.
- Quest detail modals and quest hero icons are displayed in leaderboard and locker room sections.

## Team and leaderboard integration

- Teams and leagues metadata are consumed from backend `/api/teams` and `/api/leagues`.
- Leaderboard displays and team-scoped ranking views align with backend leaderboard contracts.
- Favorite-team interactions influence quest and leaderboard context where backend eligibility requires it.
- Team detail modals show team metadata, logos, and associated leaderboard rankings.

## Locker room and social

- Social feed with post creation, commenting, and content moderation (hide/report UGC).
- Featured games carousel with daily pick'em, spin wheel, and guess-the-player mini-games.
- User profile hover cards and explore sections for fans and teams.
- D-Sports Cash balance display and D-Sports Hub entry point.

## Profile and achievements

- Milestone avatars with progressive visual upgrades based on user achievements.
- Achievement cards, chips, and detail modals with badge images.
- Follow/following lists with profile navigation.
- Points history modal for tracking engagement rewards.

## Push notifications

- OneSignal integration (`react-native-onesignal`) for push notification delivery.
- In-app notification center at `app/notifications.tsx`.
- Notification settings management in `app/settings/notifications.tsx`.

## Widgets and Live Activities

- iOS home screen widgets showing rank or wallet points (`RankOrPointsWidget`).
- iOS Live Activities for score and status updates (`LiveActivityStatus`).
- Android home screen widgets via `react-native-android-widget`.