Implement the core timer feature following the src/features/ architecture: - useTimerEngine hook: drift-free Date.now() delta countdown (100ms tick), explicit state machine (IDLE → GET_READY → WORK → REST → COMPLETE), event emitter for external consumers (PHASE_CHANGED, ROUND_COMPLETED, COUNTDOWN_TICK, SESSION_COMPLETE), auto-pause on AppState interruption (phone calls, background), expo-keep-awake during session - TimerDisplay component: full-screen animated UI with 600ms color transitions between phases, pulse animation on countdown, flash red on last 3 seconds, round progress dots, IDLE/active/COMPLETE views - TimerControls component: stop/pause-resume/skip buttons with Ionicons - Timer route (app/timer.tsx): fullScreenModal wiring hook → display - Home screen: dark theme with START button navigating to /timer - Project docs: CLAUDE.md (constitution), PRD v1.1, skill files - Shared constants: PHASE_COLORS, TIMER_DEFAULTS, formatTime utility - Types: TimerPhase, TimerState, TimerConfig, TimerActions, TimerEvent Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
124 lines
5.9 KiB
Markdown
124 lines
5.9 KiB
Markdown
# 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
|