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
147 changes: 103 additions & 44 deletions repositories/d-sports-engage-native.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,130 @@ 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.17.3**) is the native mobile app for D-Sports. It mirrors the core PWA experience on iOS, Android, and web: 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.
```bash
# Install dependencies
bun install

# Start development server
bunx expo start
# Press 'a' for Android, 'i' for iOS, or scan QR 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 54, React Native 0.81, React 19 |
| Auth | Clerk (Expo) |
| Payments | RevenueCat (react-native-purchases) |
| Web3 | Thirdweb 5.x (Arbitrum, Ethereum, Polygon) |
| State | Zustand 5 + MMKV 4 persistence |
| UI | Lucide React Native, Reanimated 4 |
| Navigation | Expo Router 6 (typed routes) |
| Monitoring | Sentry, OneSignal |
| 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.
- **Shop** — Collectibles, cart, coin bundles, fiat (RevenueCat) and crypto (Thirdweb) checkout
- **Leaderboard** — Rankings, filters, and team-scoped views
- **Locker room** — Social feed, quests, daily games (Pick'Em, Spin Wheel, Guess the Player)
- **Profile** — User profile, achievements, badges, milestone avatars, follow lists
- **Settings** — Account, appearance, accessibility, notifications, support, legal, changelog
- **Theme** — Dark/light mode (default dark, base `#0a0e1a`)

## Project structure

```tree
app/
├── (auth)/ # Login, signup, SSO callback, password reset
├── (onboarding)/ # New user onboarding flow
├── (tabs)/ # Main tab navigation (5 tabs)
│ ├── wallet.tsx # Wallet screen (JSX only — logic in hook)
│ ├── shop.tsx # Shop screen (JSX only — logic in hook)
│ ├── leaderboard/ # Leaderboard with team sub-routes
│ ├── locker-room/ # Social feed with game sub-routes
│ └── profile.tsx # User profile
├── settings/ # 15+ settings pages
└── _layout.tsx # Root layout with providers + auth guard

components/
├── wallet/ # 9 extracted wallet sub-components
├── shop/ # 7 extracted shop sub-components
├── locker-room/ # Feed, quests, games, explore components
├── leaderboard/ # Base leaderboard and team views
├── profile/ # Achievements, badges, milestone avatar
├── settings/ # Setting items, sections, modals, tabs
├── ui/ # Reusable UI primitives
└── Icon/ # Lucide icon wrapper

hooks/ # Feature hooks (wallet, shop, feed, etc.)
lib/api/ # API client modules with MMKV cache
context/ # User, collectibles, navbar, action contexts
theme/ # Colors, typography, spacing tokens
```

## Environment variables

All runtime variables use the `EXPO_PUBLIC_` prefix. You need to configure the following in your `.env`:

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

## EAS build profiles

Builds are managed through EAS with the following profiles:

| Profile | Use case | Distribution |
| --------------------- | --------------------------------- | ------------ |
| `development` | Dev client (simulator) | Internal |
| `development-device` | Dev client (physical device) | Internal |
| `preview` | Internal testing (APK on Android) | Internal |
| `staging` | Pre-release validation | Auto-increment |
| `production` | App Store / Play Store | Auto-increment |

```bash
# Development build
bun run build:dev

# Preview build
bun run build:preview

# Production build + auto-submit (iOS)
bun run build:submit:ios

# OTA update
bun run update
```

## 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.

## Quest and pass UX integration
- Retry/caching logic and auth token injection are centralized in `lib/api/client.ts`.
- MMKV cache-first fetching via `lib/api/cache.ts` provides offline resilience.

- Quest UI now 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.
## Checkout and payments

## Team-aware experiences

- Team discovery, favorite-team interactions, and leaderboard context are integrated across locker room and profile surfaces.
- Team and league metadata is sourced from backend sync pipelines fed by the `leagues` repository.
- **Fiat payments** — RevenueCat handles Apple IAP (native), Google Play (native), and Stripe (web).
- **Crypto payments** — Thirdweb SDK signs on-chain transactions via `POST /api/checkout/crypto` and `POST /api/checkout/crypto/verify` on the PWA backend. Supported chains: Arbitrum (default), Ethereum, Polygon.

## Compliance and legal: pack opening odds

- Native odds disclosure behavior is documented with policy-aligned copy and evidence requirements.
- Disclosure values must come from backend payloads and remain visible/accessible near open actions.

## 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.

## Deep dives

- [Architecture](/repositories/d-sports-engage-native/architecture)
Expand Down
85 changes: 69 additions & 16 deletions repositories/d-sports-engage-native/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,81 @@ title: "Native architecture"
description: "Architecture overview for d-sports-engage-native application layers and platform behavior."
---

## App architecture
## Routing

The native app is structured around Expo Router screens, feature-oriented components, shared hooks, and API modules.
The app uses **Expo Router 6** with file-based routing and typed routes enabled. Route groups organize the navigation hierarchy:

- 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.
| Route group | Purpose |
| ----------------- | ----------------------------------------- |
| `(auth)/` | Login, signup, SSO callback, password reset |
| `(onboarding)/` | New user onboarding flow |
| `(tabs)/` | Main 5-tab navigation |
| `settings/` | Settings pages with nested modals/tabs |

## State and context boundaries
The root layout (`app/_layout.tsx`) wraps the app in provider hierarchy (Clerk, RevenueCat, Thirdweb, user context, theme, accessibility) and handles auth-based redirects.

- 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.
## Screen-hook pattern

## API client and retry behavior
Screen files contain **only imports and JSX**. All state, effects, and handlers live in dedicated hooks:

- 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.
- `hooks/use-wallet-screen.ts` — wallet state, token fetch, 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 loading, pagination, interactions

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

## Tab bar architecture

The tab bar implementation differs by platform:

- **iOS** — `app/(tabs)/_layout.ios.tsx` uses `NativeTabs` from `expo-router/unstable-native-tabs` for system tab bar behavior. Uses `systemChromeMaterialDark` material with gold selection tint (`#FFD700`).
- **Android and web** — `app/(tabs)/_layout.tsx` renders a custom `PillTabBar` overlay with `expo-blur` and tints from `tab-config.ts`.
- **Shared config** — `app/(tabs)/tab-config.ts` defines tab order, SF Symbol pairs (iOS), and active-tab pathname matching rules.

## State management

| Layer | Technology | Scope |
| ---------------- | ---------------- | ------------------------------ |
| Global store | Zustand 5 | Theme, cart, points |
| Persistence | MMKV 4 | Synchronous read/write |
| Auth and profile | React Context | `UserContext` in `context/` |
| Collectibles | React Context | `CollectiblesContext` |
| UI visibility | React Context | Navbar visibility, FAB state |
| Accessibility | React Context | Font scale, reduced motion |

Zustand persistence uses an MMKV adapter (`services/storage.ts`). The store (`services/store.ts`) provides `getItem<T>()`, `setItem()`, and `removeItem()`.

## API client layer

All network calls route through `lib/api/*` modules:

- `lib/api/client.ts` — base HTTP client with auth token injection and error normalization
- `lib/api/cache.ts` — `fetchWithCache()` MMKV cache-first fetching for offline resilience
- Domain modules: `wallet-api`, `shop-api`, `user-api`, `quests-api`, `leaderboard-api`, `locker-room-api`, `teams-api`, `collectibles-api`, `checkout-api`, `games-api`
- `lib/api/index.ts` — `useApi()` hook that exposes all modules

Quest, reward, and team flows consume backend eligibility as the source of truth.

## Theme system

- `theme/colors.ts` — brand colors (Gold `#F5C842`, Royal Blue `#4169E1`), dark/light palettes with base dark `#0a0e1a`
- `theme/typography.ts` and `theme/fonts.ts` — type scale and font definitions
- `theme/spacing.ts` — spacing tokens
- `components/theme-provider.tsx` — `useTheme()` hook provides `resolvedTheme`

## 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** — Native tab bar (Liquid Glass), Apple Sign-In, haptic feedback, system push via OneSignal
- **Android** — Custom pill tab bar with blur, edge-to-edge layout, adaptive icon
- **Web** — PWA-ready (`display: standalone`), responsive `maxWidth: 480px` container (`components/layout/AppScreen.tsx`), web hover states via `WebHoverWrapper`, keyboard navigation support
- Haptics, modal controls, and animations use platform-safe fallbacks via Reanimated 4

## Path aliases

Import using the `@/*` alias (maps to project root):

```typescript
import { useUser } from "@/context/user-context";
import { getTokenColors } from "@/lib/token-utils";
import type { Token } from "@/types/wallet.types";
```
50 changes: 49 additions & 1 deletion repositories/d-sports-engage-native/feature-mapping.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,70 @@ description: "Native feature coverage and parity mapping against backend/PWA beh

## Feature parity with backend/PWA

`d-sports-engage-native` targets high parity with `d-sports-api` feature behavior while optimizing for mobile UX patterns.
`d-sports-engage-native` targets high parity with `d-sports-api` feature behavior while optimizing for mobile UX patterns. The table below summarizes surface coverage:

| Surface | Native status | Key components |
| -------------------- | ------------- | --------------------------------------- |
| Wallet | Full | Token list, holdings, pack opening, crypto checkout |
| Shop | Full | Collectibles, cart, coin bundles, fiat + crypto |
| Leaderboard | Full | Global and team-scoped rankings |
| Locker room | Full | Feed, quests, daily games |
| Profile | Full | Achievements, badges, milestone avatars, follows |
| Settings | Full | 15+ pages including account deletion |
| Notifications | Full | OneSignal push + in-app notifications |
| Onboarding | Full | Multi-step team selection flow |

## Wallet and pack opening

- 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.
- Opened packs section tracks previously opened pack contents.
- Token detail modals show price history, send/receive actions, and connected wallet info.

## Shop and checkout

- Collectible browsing with rarity-based card styling and 3D model viewers (GLB via Filament on native, Three.js on web).
- Cart with quantity management, coin bundles, and featured pack carousels.
- **Fiat checkout** — RevenueCat handles Apple IAP, Google Play, and Stripe (web).
- **Crypto checkout** — Thirdweb SDK for on-chain transactions. Chains: Arbitrum (default), Ethereum, Polygon. Flow: wallet select → `prepareTransaction` → `sendTransaction` → poll verification.

## 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 show requirements, progress, and reward previews.

## Daily games

- **Daily Pick'Em** — team-based prediction game with streak tracking.
- **Daily Spin Wheel** — animated prize wheel with reward distribution.
- **Guess the Player** — player identification game with hint system.

Games are surfaced in the locker room via the `FeaturedGamesCarousel` component and backed by `lib/api/games-api.ts`.

## 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 roster, stats, and fan community info.

## Profile and achievements

- Profile cards with header, stats, and follow/following counts.
- Achievement system with cards, chips, and detail modals.
- Milestone avatars with level-based visual progression.
- Badge system with cached images and asset resolution via `lib/badge-utils.ts`.
- Points history modal with transaction log.

## Settings

- **Account** — profile editing, connected accounts, blocked users, security, account deletion
- **Appearance** — theme toggle (dark/light)
- **Accessibility** — font scale, reduced motion, screen reader optimizations
- **Notifications** — push notification preferences
- **Support** — help center, contact support, report a problem
- **Legal** — terms of service, privacy policy, EULA
- **Changelog** — in-app version history
Loading