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
82 changes: 52 additions & 30 deletions repositories/d-sports-engage-native.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,72 @@ 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.4**) 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 54, React Native 0.81, React 19 |
| Auth | Clerk (`@clerk/clerk-expo`) |
| Payments | RevenueCat (`react-native-purchases`) |
| Web3 | Thirdweb |
| State | Zustand 5 |
| Storage | MMKV |
| UI | Lucide React Native |
| Navigation | Expo Router 6 |
| Push | OneSignal (`react-native-onesignal`) |
| Error tracking | Sentry (`@sentry/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** — Tokens, holdings, pack opening, send/receive, crypto checkout (via PWA backend)
- **Shop** — Collectibles, cart, coin bundles, fiat (RevenueCat) and crypto checkout
- **Leaderboard** — Per-team and global rankings with team-slug routes
- **Locker room** — Social feed, quest center, and mini-games (Daily Spin Wheel, Guess the Player, Daily Pick'em)
- **Profile** — User profile, milestone avatar rings, achievements, follower/following lists, points history
- **Settings** — Account, accessibility, appearance, notifications, support, legal, and in-app account deletion
- **Theme** — Dark mode default (base `#0a0e1a`, gold `#F5C842`, blue `#4169E1`)

## Environment variables

The app reads `EXPO_PUBLIC_*` environment variables at runtime. You need to set these in a `.env` file at the repo root:

| Variable | Purpose |
| -------- | ------- |
| `EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk authentication |
| `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 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`.

## EAS builds and OTA updates

The repo includes EAS build profiles in `eas.json` and a GitHub Actions workflow (`.github/workflows/eas-update.yml`) for OTA updates:

- Pushes to `develop` publish an OTA update to the **develop** branch.
- Pushes to `main` publish an OTA update to the **main** branch.
- Build commands: `bun run build:dev`, `bun run build:preview`, `bun run build:prod` (all via `eas-cli`).

## 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 @@ -65,9 +86,10 @@ icon: "smartphone"
## Getting started

1. Clone the repository and run `bun install`.
2. Configure environment (Clerk, RevenueCat, Thirdweb, API base URL) per repo README.
2. Create a `.env` file with the required environment variables listed above.
3. Run `bunx expo start`.
4. For development builds: `bun run build:dev` (EAS) or run with Expo dev client.
5. For native builds: `expo run:ios` or `expo run:android`.

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

Expand Down
72 changes: 65 additions & 7 deletions repositories/d-sports-engage-native/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,82 @@ description: "Architecture overview for d-sports-engage-native application layer

The native app is structured around Expo Router screens, 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.
- **Routing:** `app/*` with grouped routes — `(tabs)` for main navigation, `(auth)` for login/signup, `(onboarding)` for new users, and `settings/` for nested settings pages.
- **Feature logic:** extracted hooks (`hooks/use-wallet-screen.ts`, `hooks/use-shop-screen.ts`, etc.) keep screen files as thin JSX render shells.
- **Shared contexts:** `UserContext` (auth, profile, team membership), `CollectiblesContext` (owned packs/items), `NavBarVisibilityContext`, and `CreateActionContext`.

## Project structure

```
app/
├── (auth)/ # Login/signup (Clerk email+password, Apple, Google)
├── (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 with [teamSlug] routes
│ ├── locker-room/ # Social feed with game routes
│ └── profile.tsx # User profile
├── settings/ # Settings pages with nested modals/tabs
└── _layout.tsx # Root layout with providers + auth protection

components/
├── wallet/ # 9 wallet sub-components with barrel export
├── shop/ # 7 shop sub-components
├── locker-room/ # Locker room + game components
├── leaderboard/ # Leaderboard components
├── profile/ # Profile, achievements, milestones
├── settings/ # Settings sections, modals, tabs
├── ui/ # Reusable primitives (Button, TextField, etc.)
└── Icon/ # Icon wrapper using lucide-react-native

hooks/ # Feature hooks (use-wallet-screen, use-shop-screen, etc.)
lib/api/ # API client modules (wallet, shop, user, quests, etc.)
types/ # Shared types (wallet, shop, checkout, api)
constants/ # Shared constants (wallet, shop, locker room)
context/ # React context providers
services/ # Zustand store, MMKV storage, core types
theme/ # Colors, fonts, spacing, typography
```

## State and context boundaries

- Local/ephemeral UI state lives near feature hooks and components.
- Cross-screen state is managed with context providers and persisted storage where required.
- **Zustand** store in `services/store.ts` with MMKV persistence for theme, cart, and points.
- 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.
- All network calls route through `lib/api/*` modules with a base client in `lib/api/client.ts`.
- `lib/api/index.ts` exposes a `useApi()` hook for all API modules (wallet, shop, user, quests, leaderboard, locker room, teams, collectibles, checkout).
- `lib/api/cache.ts` provides `fetchWithCache()` for MMKV cache-first fetching.
- Client wrappers handle auth token propagation, error normalization, and retry strategy.
- Quest/reward/team flows should consume backend eligibility as source of truth.

## Platform-specific tab bar

The tab navigation uses different implementations per platform:

- **iOS:** `app/(tabs)/_layout.ios.tsx` uses `NativeTabs` from `expo-router/unstable-native-tabs` (system UIKit tab bar). Uses `systemChromeMaterialDark` with gold selection tint (`#FFD700`).
- **Android and web:** `app/(tabs)/_layout.tsx` uses JS `Tabs` with a hidden default bar and a custom `PillTabBar` overlay. Android uses `expo-blur` for the blur surface.
- **Shared config:** `app/(tabs)/tab-config.ts` defines tab order, SF Symbol pairs, and active-tab pathname resolution.

## Checkout and payments

- **Fiat:** RevenueCat (`lib/revenuecat/provider.tsx`) handles Apple IAP (native), Google Play (native), and Stripe (web).
- **Crypto:** `lib/api/checkout-api.ts` calls the PWA backend (`POST /api/checkout/crypto`). On-chain transactions use Thirdweb SDK via `lib/crypto/send-transaction.ts`. Supported chains: Arbitrum (default), Ethereum, Polygon.

## Push notifications

OneSignal is integrated via `react-native-onesignal` and the `onesignal-expo-plugin`. Subscription management is in `lib/onesignal-subscription.ts`.

## Error monitoring

Sentry (`@sentry/react-native`) is configured via the Expo plugin in `app.json`. Runtime initialization happens in `app/_layout.tsx`.

## 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.
- iOS/Android platform differences are handled in native-specific component files (e.g. `_layout.ios.tsx`).
- Web-target support exists with responsive layout (`components/layout/AppScreen.tsx`, max width 480px) and web hover states.
- Haptics, modal controls, and animation handling are implemented with platform-safe fallbacks.
- Path alias `@/*` maps to the project root for all imports.
32 changes: 31 additions & 1 deletion repositories/d-sports-engage-native/feature-mapping.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ description: "Native feature coverage and parity mapping against backend/PWA beh
## Wallet and pack opening

- Wallet screens consume balances, token data, and secure key/pin flows from backend APIs.
- **Send and receive** — send on-chain transactions via `lib/crypto/send-transaction.ts`; receive modal shows wallet address with copy and QR code.
- Pack browsing, purchase, and open flows use backend-driven states and inventory refresh behavior.
- Odds-disclosure surfaces read backend-provided probability payloads.

Expand All @@ -18,9 +19,38 @@ description: "Native feature coverage and parity mapping against backend/PWA beh
- 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 center uses MMKV cache with TTL-based invalidation and refetches on tab focus.

## 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.
- Leaderboard displays use per-team stack routes (`/leaderboard/[teamSlug]`) and team-scoped ranking views.
- Favorite-team interactions influence quest and leaderboard context where backend eligibility requires it.
- Team logos are resolved through `lib/team-logo-utils.ts` with protocol normalization and error fallbacks.

## Locker room and mini-games

- Social feed with post creation, comments, and user-generated content moderation (report, hide).
- **Daily Spin Wheel** (`components/locker-room/DailySpinWheelGame.tsx`) — daily reward spin with segment/outcome alignment and claim flows.
- **Guess the Player** (`components/locker-room/GuessThePlayerGame.tsx`) — player identification game.
- **Daily Pick'em** (`components/locker-room/DailyPickEmGame.tsx`) — daily prediction game.
- Featured games carousel with dedicated stack routes (`/locker-room/wheel-spin`, `/locker-room/player-guess`).
- Explore teams and explore fans carousels with web drag support.

## Profile and achievements

- User profile with milestone avatar rings (tier-colored SVG ring based on reward milestones).
- Achievement cards, chips, and detail modals with rarity styling.
- Points history modal with chronological breakdown by kind (quest, game, onboarding, other).
- Follower/following lists with follow/unfollow from public profiles.

## Authentication

- Clerk email and password sign-in with OTP email verification for new users.
- Two-factor authentication support (authenticator app, SMS, backup code).
- OAuth via Apple and Google.

## Notifications

- Push notifications via OneSignal with subscription management in `lib/onesignal-subscription.ts`.
- In-app notification screen at `app/notifications.tsx`.