# TabataGo — CLAUDE.md > Lis ce fichier EN ENTIER avant chaque session. C'est la constitution du projet. ## Projet Application mobile Tabata (iOS + Android) construite avec Expo SDK 52 + Expo Router v3. Modèle freemium via RevenueCat. Analytics via PostHog. Offline-first. ## Environnement de développement **Test sur device physique via Expo Go** — pas de simulateur iOS. - Scanner le QR code affiché par `npx expo start` avec l'app Expo Go sur le téléphone - Le téléphone et le Mac doivent être sur le **même réseau Wi-Fi** - En cas de problème réseau : `npx expo start --tunnel` (utilise ngrok, plus lent mais fiable) ### Contraintes Expo Go à respecter - **Pas de modules natifs custom** — uniquement les modules inclus dans le SDK Expo Go - `react-native-purchases` (RevenueCat) **ne fonctionne PAS dans Expo Go** → mocker le paywall en dev, tester sur build EAS uniquement - `expo-notifications` fonctionne partiellement dans Expo Go → tester les notifications sur build EAS dev - Modules **compatibles Expo Go SDK 52** (utilisables sans build) : `expo-av`, `expo-haptics`, `expo-keep-awake`, `expo-router`, `expo-secure-store`, `@react-native-async-storage/async-storage`, `expo-localization`, `react-native-posthog` ### Workflow de test 1. **Expo Go** → développement UI, timer, audio, exercices (90% du dev) 2. **EAS Build (Development)** → tester RevenueCat, notifications avancées 3. **EAS Build (Production)** → build final App Store / Play Store ## Stack technique — règles non-négociables | Domaine | Solution | Interdit | |---|---|---| | Framework | Expo SDK 52 (managed workflow) | Bare workflow sauf si absolument nécessaire | | Navigation | Expo Router v3 (file-based) | React Navigation seul | | State global | Zustand + AsyncStorage | Redux, MobX, Context pour state global | | Timer engine | Date.now() delta dans un hook isolé | setInterval seul (drift inacceptable) | | Audio | expo-av avec AVAudioSession | expo-audio (instable), react-native-sound | | Paiements | react-native-purchases (RevenueCat) | IAP natif direct — **MOCKER en dev Expo Go** | | Analytics | react-native-posthog | Firebase Analytics, Amplitude | | Styles | StyleSheet.create() | Styles inline, Tailwind, NativeWind | | Types | TypeScript strict (`"strict": true`) | any, @ts-ignore sauf justification | ## Architecture — structure de fichiers ``` src/ features/ timer/ hooks/useTimerEngine.ts ← moteur central, AUCUN JSX hooks/useTimerSync.ts ← synchronise audio + exercice sur les events timer components/TimerDisplay.tsx ← affichage uniquement, reçoit tout par props components/TimerControls.tsx ← boutons start/pause/stop/skip types.ts ← TimerPhase, TimerState, TimerConfig audio/ hooks/useAudioEngine.ts ← gestion expo-av, preload, crossfade hooks/useAudioSettings.ts ← préférences utilisateur (ambiance, volume) data/tracks.ts ← catalogue des tracks (offline) data/sounds.ts ← catalogue des signaux de phase types.ts exercises/ hooks/useExercise.ts ← sélection, navigation entre exercices components/ExerciseDisplay.tsx ← rendu selon la phase courante components/ExerciseGif.tsx ← affichage GIF avec fallback data/exercises.ts ← les 38 exercices (offline) types.ts programs/ hooks/useProgram.ts components/ProgramBuilder.tsx data/defaultPrograms.ts onboarding/ hooks/useOnboarding.ts screens/ ← 6 écrans (1 fichier par écran) paywall/ hooks/usePaywall.ts ← RevenueCat wrapper components/PaywallScreen.tsx shared/ components/ ← Button, Card, Typography, etc. hooks/ ← useHaptics, useKeepAwake, useAppState utils/ ← formatTime, etc. constants/ ← couleurs, durées par défaut app/ ← Expo Router (fichiers de route uniquement) (tabs)/ index.tsx ← Home history.tsx settings.tsx timer/index.tsx programs/[id].tsx onboarding/index.tsx paywall/index.tsx ``` ## Règles de code 1. **Un fichier = une responsabilité** — si un hook dépasse 150 lignes, il doit être découpé 2. **Toute logique métier dans les hooks** — les composants n'ont QUE du JSX + appel de hooks 3. **Barrel exports** — chaque feature expose un `index.ts` propre 4. **Tests colocalisés** — `ComponentName.test.tsx` dans le même dossier 5. **Pas d'effet secondaire dans le render** — tout dans useEffect ou les handlers 6. **Typage strict des events** — pas de `any` dans les callbacks de timer/audio ## Commandes du projet ```bash npx expo start # dev — scanner le QR avec Expo Go npx expo start --tunnel # si problème réseau Wi-Fi (ngrok) npx expo start --clear # vider le cache Metro si comportement bizarre jest --watchAll # tests en continu eas build --profile development # build dev (pour tester RevenueCat, notifs) eas build --platform ios # build TestFlight npx expo export # bundle production ``` ## Comment utiliser les skills Quand tu travailles sur une feature spécifique, lis le skill correspondant : - Timer → `.claude/skills/timer/SKILL.md` - Audio → `.claude/skills/audio/SKILL.md` - Exercices → `.claude/skills/exercises/SKILL.md` - Workflow général → `.claude/skills/workflow/SKILL.md` ## Priorité d'implémentation V1 1. `useTimerEngine` + `TimerDisplay` (plein écran) 2. `useAudioEngine` + synchronisation avec timer 3. `ExerciseDisplay` + données des 38 exercices 4. Synchronisation triple timer × audio × exercice 5. Onboarding 6 écrans + mini-démo live 6. Paywall RevenueCat 7. Streak + historique 8. Notifications de rappel