diff --git a/repositories/d-sports-engage-native.mdx b/repositories/d-sports-engage-native.mdx index e79c1b6..5ffaea8 100644 --- a/repositories/d-sports-engage-native.mdx +++ b/repositories/d-sports-engage-native.mdx @@ -35,10 +35,11 @@ icon: "smartphone" ## 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. +- Comprehensive accessibility support added: VoiceOver, Voice Control, larger text, high contrast, reduced motion, and differentiate-without-color across all main screens. +- iOS tab bar now uses `NativeTabs` (`expo-router/unstable-native-tabs`) with system tab bar; Android and web use a custom `PillTabBar` with blur overlay. +- Modular architecture enforced: screen files are thin render shells, all styles extracted to `*.styles.ts` files, one component per file with barrel exports. +- EAS build profiles formalized for development, preview, staging, and production with GitHub Actions OTA workflow. +- Settings and account flows expanded, including in-app account deletion and richer support/data controls. ## Backend integration surfaces @@ -62,15 +63,60 @@ icon: "smartphone" - 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. +## Environment variables + +All runtime variables use the `EXPO_PUBLIC_*` prefix so they are accessible in the Expo app. Create a `.env` file in the repo root: + +| Variable | Purpose | +| -------- | ------- | +| `EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk authentication (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 for web3 features | +| `EXPO_PUBLIC_REVENUECAT_API_KEY` | RevenueCat SDK key for in-app purchases | +| `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 (client-side features only) | +| `EXPO_PUBLIC_SUPABASE_KEY` | Supabase publishable anon key | + + +Only `EXPO_PUBLIC_*` keys are bundled into the app. Server-only secrets like `SENTRY_AUTH_TOKEN` are set in EAS build secrets or Xcode environment variables. + + ## 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`. +2. Copy `.env` and fill in the required `EXPO_PUBLIC_*` values listed above. +3. Run `bunx expo start` — press **a** for Android, **i** for iOS, or scan the QR code with Expo Go. 4. For development builds: `bun run build:dev` (EAS) or run with Expo dev client. +5. TypeScript check: `bun tsc --noEmit`. The app targets both native and web (responsive) and uses the same backend (d-sports-api) as the PWA for API and checkout flows. +## EAS build profiles + +Builds use [Expo Application Services (EAS)](https://expo.dev/eas) configured in `eas.json`: + +| Profile | Channel | Use case | +| ------- | ------- | -------- | +| `development` | `development` | Dev client with simulator support | +| `development-device` | `development` | Dev client on physical device | +| `preview` | `preview` | Internal distribution (APK on Android) | +| `staging` | `staging` | Pre-production with auto-increment | +| `production` | `production` | App Store / Play Store release | + +Common build commands: + +```bash +bun run build:dev:ios # development build for iOS simulator +bun run build:preview:android # preview APK for Android +bun run build:prod:ios # production build for iOS +bun run build:submit:ios # production build + auto-submit to App Store +``` + +## CI/CD + +A GitHub Actions workflow (`.github/workflows/eas-update.yml`) publishes OTA updates via `eas update` on pushes to `develop` and `main` branches. The workflow uses Bun for dependency installation and the Expo GitHub Action for EAS CLI setup. + ## Deep dives - [Architecture](/repositories/d-sports-engage-native/architecture) diff --git a/repositories/d-sports-engage-native/architecture.mdx b/repositories/d-sports-engage-native/architecture.mdx index af786e3..97083ad 100644 --- a/repositories/d-sports-engage-native/architecture.mdx +++ b/repositories/d-sports-engage-native/architecture.mdx @@ -7,24 +7,71 @@ 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 for `(tabs)`, `(auth)`, `(onboarding)`, and `settings/`. +- **Feature logic:** extracted hooks (`hooks/use-wallet-screen.ts`, `hooks/use-shop-screen.ts`, etc.) keep screen files as thin render shells. +- **Shared contexts:** user, collectibles, accessibility, navbar visibility, and create-action state. + +## Modular architecture + +The codebase enforces strict modular patterns: + +- **Screen files are thin render shells** — files in `app/(tabs)/` contain only imports and JSX. All state, effects, and handlers live in custom hooks under `hooks/`. +- **External stylesheets** — `StyleSheet.create()` is never placed inside component files. All styles go in `styles/` subdirectories as `ComponentName.styles.ts`. +- **One component per file** — each component gets its own `.tsx` file with a named export. Related components are grouped in `components//` with a barrel `index.ts`. +- **Centralized types and constants** — shared types live in `types/.types.ts`, constants in `constants/.constants.ts`. +- **File size limit** — no file should exceed ~300 lines; large files are split into sub-components, hooks, styles, and types. +- **Path aliases** — all imports use `@/*` (maps to project root). + +## Tab bar architecture + +The app uses platform-specific tab bar implementations: + +### iOS + +`app/(tabs)/_layout.ios.tsx` uses `NativeTabs` from `expo-router/unstable-native-tabs` for the system tab bar. Key details: +- Uses `systemChromeMaterialDark` background with gold selection tint (`#FFD700`). +- Wallet tab shows a numeric `Badge` for unopened packs. +- SF Symbol pairs are defined in `app/(tabs)/tab-config.ts`. +- `disableTransparentOnScrollEdge` prevents the bar from losing its dark material on scroll. + +### Android and web + +`app/(tabs)/_layout.tsx` uses the JS `Tabs` component with a hidden default bar and a custom `PillTabBar` overlay. Android uses `expo-blur` (`BlurView`) for the pill background. + +### Shared config + +`app/(tabs)/tab-config.ts` defines tab order, SF Symbol pairs for iOS, and helper functions like `getActiveTabIndex` and `isPublicProfileStackRoute`. ## 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. -- User/session-sensitive state is coordinated with backend auth and profile sync endpoints. +- **Zustand** store in `services/store.ts` with MMKV persistence for theme, cart, and points. +- **React Context** providers in `context/`: `UserContext`, `CollectiblesContext`, `NavBarVisibilityContext`, `CreateActionContext`, and `AccessibilityContext`. + +## Accessibility architecture + +The app supports all 9 Apple Accessibility Nutrition Label categories. The central `AccessibilityContext` (`context/accessibility-context.tsx`) manages: + +- **VoiceOver and Voice Control** — all interactive elements have `accessibilityRole`, `accessibilityLabel`, `accessibilityHint`, and `accessibilityState`. +- **Larger text** — respects iOS Dynamic Type via `AccessibilityInfo` with in-app 1.25× toggle, capped at 2× via `maxFontSizeMultiplier`. +- **Reduced motion** — `ReducedMotionConfig` from `react-native-reanimated` at the root layout, plus in-app toggle. +- **High contrast** — `theme/colors.ts` exports `darkHighContrast` and `lightHighContrast` variants; activated by in-app toggle or iOS Bold Text setting. +- **Differentiate without color** — directional arrows (▲/▼) alongside price change colors, text labels on rarity badges. + +See [Accessibility compliance](/repositories/d-sports-engage-native/compliance/accessibility) for the full implementation matrix. ## 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. +- `lib/api/client.ts` is the base HTTP client with auth token injection. +- `lib/api/cache.ts` provides `fetchWithCache()` using MMKV for 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`. +- Quest/reward/team flows consume backend eligibility as source of truth. ## 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:** system tab bar via `NativeTabs`, native haptics, Apple authentication. +- **Android:** custom pill tab bar with `BlurView`, platform keyboard handling (`softwareKeyboardLayoutMode: resize`). +- **Web:** responsive `maxWidth: 480px` container via `AppScreen`, hover states via `WebHoverWrapper`, PWA manifest with `display: "standalone"`. +- Haptics, modal controls, and animation handling use platform-safe fallbacks.