Mobile·6 min de lecture·1,105 mots

Guide dev mobile

Development Guide — Mobile (mobile-staging/)

Prerequisites

  • Node.js ≥ 20 (Expo 54 compatible)
  • npm ≥ 10
  • Expo CLI : npm i -g eas-cli (≥ 18.12.3)
  • iOS : macOS + Xcode (pour simulator) — Apple Developer account si build
  • Android : Android Studio + emulator OU device physique (USB debugging)
  • Compte Expo (account ouattaradfabrice configuré sur project wari-mobile)
  • Apple Developer (Team 9HTKV7262K, ascAppId 6768885815)
  • Firebase project (wari-mobile-911d2) avec google-services.json commité

Source de vérité dev

⚠️ Ne pas développer dans mobile-staging/ sur le VPS.

Le code mobile vit sur la machine fabrice (fabrice@192.168.1.152, user fabrice), dans ~/DEVELOPPEMENT/. Le dossier mobile-staging/ sur le VPS est un miroir pour consultation.

Accès depuis le VPS via reverse SSH tunnel établi par le user :

ssh -p 2222 fabrice@127.0.0.1
cd ~/DEVELOPPEMENT

Repo distant : git@github.com:ouattaradfabrice/wari-mobile.git, branche main.

Installation locale (machine fabrice)

cd ~/DEVELOPPEMENT
npm install

# Configuration Expo / EAS
npx expo login            # compte ouattaradfabrice
eas login                 # idem

# Vérifier projet
cat app.json | grep -A2 expo.extra.eas
# Doit afficher projectId: 4d8772a8-77f0-4fb1-818e-576a2f755fe1

Lancement dev

# Dev server LAN (test sur Expo Go ou dev client iOS/Android)
npx expo start --lan

# Tunnel (ngrok, accessible de n'importe où)
npx expo start --tunnel

# iOS simulator (macOS uniquement)
npm run ios

# Android emulator / device USB
npm run android

# Web : NON SUPPORTÉ (BUG-134 — app.json platforms = ["ios","android"])

Reactotron (debug réseau + Redux/Zustand) : reactotron-app & sur le bureau Ubuntu, se connecte sur 192.168.1.152:9090.

Scripts npm

{
  "start": "expo start",
  "android": "expo start --android",
  "ios": "expo start --ios",
  "test": "jest",
  "test:watch": "jest --watch",
  "lint": "eslint .",
  "lint:fix": "eslint . --fix",
  "typecheck": "tsc --noEmit"
}

Workflow Git mobile

cd ~/DEVELOPPEMENT
git status
git add .                                      # ou fichiers spécifiques
git commit -m "feat: <description courte>

- détail 1
- détail 2"
git push origin main

⚠️ Toujours SSH (git@github.com:...), jamais HTTPS+PAT. Configurer une fois :

git remote set-url origin git@github.com:ouattaradfabrice/wari-mobile.git
git remote -v   # → doit afficher git@github.com:... (pas https://)
ssh -T git@github.com   # → "Hi ouattaradfabrice!"
git config user.email 'ouattaradfabrice@gmail.com'
git config user.name 'ouattaradfabrice'

⚠️ Vérifier .gitignore couvre node_modules/, .expo/, .env*, ios/, android/ avant git add ..

Builds EAS

Profiles dans eas.json :

development → APK Android + dev client (channel development)
preview     → APK Android internal + iOS device (channel preview)
production  → App Bundle Android (Play Store) + iOS Release autoIncrement buildNumber (channel production)

Builds OTA (cas 95%)

Pour la majorité des releases, OTA suffit (pas de rebuild natif requis) :

cd ~/DEVELOPPEMENT
eas update --branch production --message "fix: BUG-XXX label court"
# ~5 min, push sur tous les devices via channel production

Cas où OTA suffit : changements TS/TSX, ajout/modif strings i18n, fix UI, changement comportement business, ajout/suppression écrans expo-router (file-based), ajout/modif hooks, refactor.

Cas où il faut un build natif (rare) :

  • Ajout/modif permissions iOS (infoPlist) ou Android (AndroidManifest)
  • Ajout d'un package Expo natif (ex. expo-haptics)
  • Bump SDK Expo (52 → 54 → 55...)
  • Changement icône / splash screen
  • Changement bundle identifier / scheme deep link
  • Changement Firebase google-services.json

Build natif iOS production

cd ~/DEVELOPPEMENT
eas build --platform ios --profile production
# 30-90 min (free tier queue) - notification quand prêt
# Le build est uploadé sur Apple, dispo dans App Store Connect (Activities)

Submit TestFlight

eas submit --platform ios --latest
# Push le dernier build vers TestFlight automatiquement
# Apple processing ~10-30 min

Build Android

eas build --platform android --profile production
# App Bundle (.aab) pour Play Store
# Play Store config pas encore active V1

Conventions code

Tirées de ~/DEVELOPPEMENT/CLAUDE.md (sur machine fabrice) + règles racine VPS :

  1. Icônes : Phosphor uniquement via lib/icons.ts (DEC-133/134/135) — jamais Ionicons/MaterialIcons/FontAwesome/emojis comme icônes UI
  2. Filtres : <FilterChip /> + <FilterSheet /> partout (DEC-137/138)
  3. Bottom sheets clavier-safe : keyboardShouldPersistTaps="handled", keyboardDismissMode="on-drag", pas de KeyboardAvoidingView sur position absolute, Keyboard.addListener iOS seulement (DEC-170)
  4. ctaPaddingBottom 2 variantes selon contexte Modal vs GerantLayout (DEC-174 — éviter double safe area)
  5. TopBar absolute : tout ScrollView tab doit lire useUIStore().topbarHeight et appliquer paddingTop: topbarHeight + SPACING.sm (DEC-153)
  6. Touch targets ≥ 44×44 partout
  7. API client : utiliser apiFetch de lib/api.ts — jamais throw, retourne { data, error, status }
  8. Routes constants dans lib/constants.ts (VITRINE_*, API_URL)
  9. Stores Zustand : 16 stores existants, pattern selectIsTenant etc. Pas de Context API.
  10. Hooks React Query : 1 par domaine, staleTime tuné 60s pour Android mid-range
  11. Pas de commentaires sauf WHY non-évident (cohérent avec backend)

Tests

cd ~/DEVELOPPEMENT
npm test                  # jest --watchAll=false par défaut
npm run test:watch
npm run typecheck         # tsc --noEmit
npm run lint
npm run lint:fix

Tests : __tests__/ avec jest + @testing-library/react-native. Setup dans jest.setup.js + jest.config.js. Couverture partielle (UI + stores + hooks). Pas de tests E2E (Detox/Maestro pas configurés).

QA manuel = TestFlight + sessions test pratique (fixtures tests-pratiques/ côté VPS).

i18n

Fichiers dans locales/<lng>/translation.json (fr, en, ar, pt). Strings extraites avec t('namespace.key') via react-i18next.

import { useTranslation } from 'react-i18next';

function MyScreen() {
  const { t } = useTranslation();
  return <Text>{t('vitrine.title')}</Text>;
}

Push notifications dev

En Expo Go, expo-notifications log un ERROR au boot (limitation SDK 53+). En dev build (apk via eas build --profile development), tout fonctionne (BUG-118 fix : require conditionnel).

Pour tester en local :

# Avec dev build seulement
eas build --platform android --profile development
# Installer l'APK sur device + scanner QR Expo

Debug commun

ProblèmeDiagnostic
Bundle Metro fail Cannot find module 'react-dom/server.node'app.json.web block présent — supprimer + platforms: ["ios","android"] (BUG-134)
expo-notifications ERROR au bootNormal en Expo Go SDK 53+ ; OK en dev build/TestFlight (BUG-118)
Header Stack inattendu sur écranManque Stack.Screen dans app/_layout.tsx racine avec headerShown: false (BUG-116)
Bouton "Se connecter" no-opRoute doit être /auth pas /auth/login (BUG-117)
Bearer 401 après cold startVérifier AuthHydrator mount + getToken() cache mémoire Android
Push pas reçu en devVérifier Firebase google-services.json + APNs cert prod + token register dans /api/mobile/push-tokens/register avec session.role correct (BUG-120/124)
Photo masquée pas blurrée fiche détailProduitGalerie prop masque à passer depuis parent (BUG-132)

Liens utiles