Skip to content
Open
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
242 changes: 211 additions & 31 deletions repositories/d-sports-engage-native.mdx
Original file line number Diff line number Diff line change
@@ -1,47 +1,227 @@
---
title: "d-sports-engage-native"
description: "Native iOS and Android app for D-Sports Engage. Expo 54, React Native, Clerk, RevenueCat, Thirdweb."
icon: "smartphone"
title: d-sports-engage-native
description: Native iOS, Android, and web app for D-Sports Engage built with Expo 54, React Native, and TypeScript.
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.10.5) is the native mobile and web app for D-Sports. It mirrors the core PWA experience on iOS, Android, and web with wallet, shop, leaderboard, locker room, and profile screens.

Check warning on line 9 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L9

Did you really mean 'leaderboard'?

- **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.
<Card title="Ecosystem overview" icon="map" href="/repositories/ecosystem-overview">
See how the native app fits with the PWA, site, and Mic'd Up.

Check warning on line 12 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L12

Did you really mean 'Mic'd'?
</Card>

## Tech stack

| Category | Technology |
| ---------- | ------------------------- |
| 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 |
| Language | TypeScript 5.9 |
| Routing | Expo Router 6 (file-based, typed routes) |
| Auth | Clerk (`@clerk/clerk-expo`) |
| Payments | RevenueCat (`react-native-purchases`) — Apple IAP, Google Play, Stripe (web) |
| Web3 | Thirdweb SDK — on-chain crypto checkout |

Check warning on line 24 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L24

Did you really mean 'Thirdweb'?

Check warning on line 24 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L24

Did you really mean 'crypto'?
| State | Zustand 5 with MMKV persistence |

Check warning on line 25 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L25

Did you really mean 'Zustand'?
| Storage | MMKV (`react-native-mmkv`) |
| Icons | Lucide React Native |

Check warning on line 27 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L27

Did you really mean 'Lucide'?
| Animations | React Native Reanimated 4 |
| Monitoring | Sentry (`@sentry/react-native`) |
| Package manager | Bun 1.3 |

## Features
## Getting started

- **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)
<Steps>
<Step title="Clone and install">
```bash
git clone <repo-url>
cd d-sports-engage-native
bun install
```
</Step>
<Step title="Configure environment variables">
Copy the `.env` file and fill in values for your environment. Only `EXPO_PUBLIC_*` keys are accessible at runtime.

## Getting started
| Variable | Purpose |
| -------- | ------- |
| `EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk authentication publishable key |
| `EXPO_PUBLIC_API_URL` | D-Sports API backend URL (e.g. `https://api.d-sports.org`) |
| `EXPO_PUBLIC_TW_CLIENT_ID` | Thirdweb client ID for web3 |
| `EXPO_PUBLIC_REVENUECAT_API_KEY` | RevenueCat API key |
| `EXPO_PUBLIC_REVENUECAT_APPSTORE_ID` | RevenueCat App Store app ID |
| `EXPO_PUBLIC_REVENUECAT_ENTITLEMENT` | RevenueCat entitlement identifier (e.g. `premium`) |
| `EXPO_PUBLIC_SUPABASE_URL` | Supabase project URL |
| `EXPO_PUBLIC_SUPABASE_KEY` | Supabase publishable (anon) key |
</Step>
<Step title="Start the development server">
```bash
bunx expo start

Check warning on line 58 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L58

Did you really mean 'bunx'?
```
Press **a** for Android, **i** for iOS, or scan the QR code with Expo Go.
</Step>
<Step title="Type-check">
```bash
bun tsc --noEmit

Check warning on line 64 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L64

Did you really mean 'tsc'?
```
</Step>
</Steps>

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

The app targets both native and web (responsive) and uses the same backend (d-sports-api) as the PWA for API and checkout flows.
```text
app/
├── (auth)/ # Login, sign-up, SSO callback, password reset
├── (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.tsx # Leaderboard screen
│ ├── locker-room.tsx # Social feed
│ └── profile.tsx # User profile
├── settings/ # Settings pages with nested modals/tabs
└── _layout.tsx # Root layout with providers + auth protection

<Card title="Ecosystem overview" icon="map" href="/repositories/ecosystem-overview">
See how the native app fits with the PWA, site, and Mic'd Up.
</Card>
components/
├── wallet/ # 9 wallet sub-components (TokenRow, ActionModal, etc.)
├── shop/ # 7 shop sub-components (CartModal, CryptoCheckoutModal, etc.)
├── locker-room/ # Locker room feed, games, quests
├── leaderboard/ # Leaderboard table and modal
├── settings/ # Settings items, sections, modals
├── layout/ # AppScreen responsive wrapper
├── ui/ # Reusable primitives (Button, TextField, WebHoverWrapper)
├── Icon/ # Icon wrapper using lucide-react-native
└── theme-provider.tsx # Theme context (dark/light)

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 # Social feed logic
├── use-carousel-scroll.ts
└── use-draggable-scroll.ts

lib/
├── api/ # API client modules (see below)
├── revenuecat/ # RevenueCat in-app purchases provider
├── crypto/ # On-chain transaction helpers
├── logger.ts # Structured logging
└── utils.ts # cn() class merging utility

context/
├── user-context.tsx # Auth, user profile, team membership
├── collectibles-context.tsx # Owned packs and items
├── navbar-visibility-context.tsx
└── create-action-context.tsx

services/
├── store.ts # Zustand global store (theme, cart, points)
├── storage.ts # MMKV persistence adapter
└── types.ts # Core types (User, Room, Team, Product)

theme/
├── colors.ts # Brand colors, dark/light palettes
├── spacing.ts # Spacing scale
└── typography.ts # Font definitions
```

## Architecture

### Modular screen pattern

Screen files in `app/(tabs)/` contain **only imports and JSX**. All state, effects, and handlers live in dedicated hooks:

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

Sub-components are extracted into `components/wallet/` and `components/shop/` with barrel exports via `index.ts`. Styles live in co-located `styles/` directories, never inline.

### API client layer

The API client in `lib/api/client.ts` provides authenticated requests using Clerk tokens with normalized `{ success, data?, error?, code? }` response envelopes.

You access all API modules via the `useApi()` hook:

```tsx
import { useApi } from "@/lib/api";

function MyComponent() {
const api = useApi();

const loadData = async () => {
const result = await api.user.getProfile();
if (result.success) {
console.log(result.data);
}
};
}
```

Available API modules: `user`, `quests`, `leaderboard`, `wallet`, `lockerRoom`, `teams`, `collectibles`, `shop`, `checkout`.

The client includes an MMKV-backed cache layer (`lib/api/cache.ts`) for offline-first data fetching.

### State management

- **Zustand** (`services/store.ts`) — global store for theme, cart, and points with synchronous MMKV persistence

Check warning on line 164 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L164

Did you really mean 'Zustand'?
- **React Context** — `UserContext` for auth and profile, `CollectiblesContext` for owned items, `NavBarVisibilityContext` for scroll-based navbar, `CreateActionContext` for FAB state

Check warning on line 165 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L165

Did you really mean 'navbar'?
- **MMKV** (`services/storage.ts`) — synchronous key-value storage via `getItem<T>()`, `setItem()`, `removeItem()`

### Checkout and payments

The app supports two payment paths:

- **Fiat** — RevenueCat handles Apple IAP (native), Google Play (native), and Stripe (web) via `lib/revenuecat/provider.tsx`
- **Crypto** — Thirdweb SDK signs on-chain transactions calling the PWA backend (`POST /api/checkout/crypto` and `POST /api/checkout/crypto/verify`). Supported chains: Arbitrum (default), Ethereum, Polygon.

Check warning on line 173 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L173

Did you really mean 'Crypto'?

Check warning on line 173 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L173

Did you really mean 'Thirdweb'?

Check warning on line 173 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L173

Did you really mean 'Arbitrum'?

Check warning on line 173 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L173

Did you really mean 'Ethereum'?

### Routing

Expo Router provides file-based routing with route groups:
- `(tabs)` — main tab navigation with animated pill tab bar
- `(auth)` — login, sign-up, SSO callback, password reset
- `(onboarding)` — new user flow

Auth protection in `_layout.tsx` automatically redirects based on authentication and onboarding state.

### Web optimization

The app is PWA-ready with `display: "standalone"` and includes:
- Responsive desktop layout (`maxWidth: 480px`) via `AppScreen` wrapper
- Web hover states on interactive components
- Keyboard navigation support
- `accessibilityRole` and `accessibilityLabel` on key elements

## EAS build profiles

| Profile | Distribution | Channel | Notes |
| ------- | ------------ | ------- | ----- |
| `development` | Internal | `development` | Dev client, iOS simulator enabled |
| `development-device` | Internal | `development` | Dev client, physical devices |
| `preview` | Internal | `preview` | APK for Android |
| `staging` | Default | `staging` | Auto-increment version |
| `production` | Default | `production` | Auto-increment version |

Run builds with:

```bash
bun run build:dev # All platforms, development
bun run build:preview:ios # iOS only, preview
bun run build:prod # All platforms, production
```

## Features

- **Wallet** — token balances, holdings, pack opening, crypto checkout

Check warning on line 212 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L212

Did you really mean 'crypto'?
- **Shop** — collectibles, cart, coin bundles, featured packs, crypto and fiat checkout

Check warning on line 213 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L213

Did you really mean 'crypto'?
- **Leaderboard** — rankings with filters and modals

Check warning on line 214 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L214

Did you really mean 'Leaderboard'?
- **Locker room** — social feed, daily pick'em, spin wheel, guess the player, quests

Check warning on line 215 in repositories/d-sports-engage-native.mdx

View check run for this annotation

Mintlify / Mintlify Validation (chronoscyberchronicles) - vale-spellcheck

repositories/d-sports-engage-native.mdx#L215

Did you really mean 'pick'em'?
- **Profile** — user profile, settings, team membership
- **Theme** — dark/light mode (default dark), gold accent (`#F5C842`)

## Path aliases

Use `@/*` to import from the project root:

```typescript
import { useUser } from "@/context/user-context";
import { getTokenColors } from "@/lib/token-utils";
import type { Token } from "@/types/wallet.types";
```