diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4f93b34 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,362 @@ +# AGENTS.md + +This file contains optimizations and best practices for working with this TabataFit Expo project. + +--- + +## 🚀 Command Optimizations + +Use the following `rtk` commands for optimal performance: + +| Command | rtk Equivalent | Speedup | Tokens Before | Tokens After | Savings | +|---------|----------------|---------|---------------|--------------|---------| +| `ls` / `tree` | `rtk ls` | 10x | 2,000 | 400 | -80% | +| `cat` / `read` | `rtk read` | 20x | 40,000 | 12,000 | -70% | +| `grep` / `rg` | `rtk grep` | 8x | 16,000 | 3,200 | -80% | +| `git status` | `rtk git status` | 10x | 3,000 | 600 | -80% | +| `git diff` | `rtk git diff` | 5x | 10,000 | 2,500 | -75% | +| `git log` | `rtk git log` | 5x | 2,500 | 500 | -80% | +| `git add/commit/push` | `rtk git` | 8x | 1,600 | 120 | -92% | +| `cargo test` / `npm test` | `rtk test` | 5x | 25,000 | 2,500 | -90% | +| `ruff check` | `rtk lint` | 3x | 3,000 | 600 | -80% | +| `pytest` | `rtk pytest` | 4x | 8,000 | 800 | -90% | +| `go test` | `rtk gotest` | 3x | 6,000 | 600 | -90% | +| `docker ps` | `rtk docker` | - | - | - | - | + +### Usage Examples + +```bash +# Instead of: ls -la src/ +rtk ls src/ + +# Instead of: cat package.json +rtk read package.json + +# Instead of: grep -r "useEffect" src/ +rtk grep "useEffect" src/ + +# Instead of: git status +rtk git status + +# Instead of: npm test +rtk test + +# Instead of: ruff check . +rtk lint +``` + +--- + +## 📱 Expo Best Practices + +### Development Workflow + +**CRITICAL: Always try Expo Go first before creating custom builds.** + +1. **Start with Expo Go**: Run `npx expo start` and scan the QR code with Expo Go +2. **Check if features work**: Test your app thoroughly in Expo Go +3. **Only create custom builds when required** + +#### When Custom Builds Are Required + +Use `npx expo run:ios/android` or `eas build` ONLY when using: +- **Local Expo modules** (custom native code in `modules/`) +- **Apple targets** (widgets, app clips, extensions via `@bacons/apple-targets`) +- **Third-party native modules** not included in Expo Go +- **Custom native configuration** that can't be expressed in `app.json` + +#### When Expo Go Works + +Expo Go supports a huge range of features out of the box: +- All `expo-*` packages (camera, location, notifications, etc.) +- Expo Router navigation +- Most UI libraries (reanimated, gesture handler, etc.) +- Push notifications, deep links, and more + +### Common Commands + +```bash +# Development +npx expo start # Start development server +npx expo start --tunnel # If network issues +npx expo start --clear # Clear cache +npx tsc --noEmit # Type check +npx expo install # Install Expo-compatible packages + +# Building +npx eas-cli@latest build --profile development # Dev build +npx eas-cli@latest build -p ios --profile production --submit # Build and submit iOS +npx testflight # Quick TestFlight shortcut + +# Development Client (when native code changes) +npx expo start --dev-client +``` + +### Code Style Rules + +#### File Naming +- Use kebab-case for file names (e.g., `workout-card.tsx`) +- Never use special characters in file names +- Always remove old route files when moving or restructuring navigation + +#### Imports +- Use path aliases from `tsconfig.json` instead of relative imports +- Prefer aliases over relative imports for refactors +- Always use import statements at the top of the file + +#### Library Preferences +- ✅ `expo-audio` not `expo-av` +- ✅ `expo-video` not `expo-av` +- ✅ `expo-image` with `source="sf:name"` for SF Symbols +- ✅ `react-native-safe-area-context` not react-native SafeAreaView +- ✅ `process.env.EXPO_OS` not `Platform.OS` +- ✅ `React.use` not `React.useContext` +- ❌ Never use modules removed from React Native: Picker, WebView, SafeAreaView, AsyncStorage +- ❌ Never use legacy expo-permissions +- ❌ Never use intrinsic elements like 'img' or 'div' unless in webview + +### Route Structure + +``` +app/ + _layout.tsx # Root layout with tabs + (tabs)/ # Group routes for tabs + _layout.tsx # Tabs layout + index.tsx # Home tab + workouts.tsx # Workouts tab + activity.tsx # Activity tab + browse.tsx # Browse tab + profile.tsx # Profile tab + player/ + [id].tsx # Workout player +``` + +#### Route Rules +- Routes belong in the `app` directory +- Never co-locate components, types, or utilities in the app directory +- Ensure the app always has a route that matches "/" +- Always use `_layout.tsx` files to define stacks + +### UI Guidelines + +#### Responsiveness +- Always wrap root component in a scroll view for responsiveness +- Use `` instead of `` +- `contentInsetAdjustmentBehavior="automatic"` should be applied to FlatList and SectionList +- Use flexbox instead of Dimensions API +- ALWAYS prefer `useWindowDimensions` over `Dimensions.get()` + +#### Styling +- Prefer flex gap over margin and padding styles +- Prefer padding over margin where possible +- Inline styles not StyleSheet.create unless reusing styles is faster +- Use `{ borderCurve: 'continuous' }` for rounded corners +- ALWAYS use a navigation stack title instead of a custom text element +- When padding a ScrollView, use `contentContainerStyle` padding +- Add entering and exiting animations for state changes + +#### Shadows +Use CSS `boxShadow` style prop. NEVER use legacy React Native shadow or elevation styles. + +```tsx + +``` + +#### Text Styling +- Add the `selectable` prop to every `` element displaying important data +- Counters should use `{ fontVariant: 'tabular-nums' }` for alignment + +#### Safe Area +- Always account for safe area with stack headers, tabs, or ScrollView/FlatList `contentInsetAdjustmentBehavior="automatic"` +- Ensure both top and bottom safe area insets are accounted for + +### Navigation Patterns + +#### Stack Configuration + +```tsx +import { Stack } from 'expo-router/stack'; + + + + +``` + +#### Links with Previews + +```tsx +import { Link } from 'expo-router'; + + + + + + + + + + + + + +``` + +#### Modal/Sheet Presentations + +```tsx +// Modal + + +// Form Sheet + +``` + +### Data Fetching + +#### Environment Variables +- Use `EXPO_PUBLIC_` prefix for client-side environment variables +- Never put secrets in `EXPO_PUBLIC_` variables (visible in built app) +- Restart the dev server after changing `.env` files + +```bash +# .env +EXPO_PUBLIC_API_URL=https://api.example.com +EXPO_PUBLIC_SUPABASE_URL=your-supabase-url +``` + +#### API Client Pattern + +```tsx +const BASE_URL = process.env.EXPO_PUBLIC_API_URL; + +export const apiClient = { + get: async (path: string): Promise => { + const response = await fetch(`${BASE_URL}${path}`); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + return response.json(); + }, +}; +``` + +#### React Query Setup + +```tsx +// app/_layout.tsx +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 60 * 5, // 5 minutes + retry: 2, + }, + }, +}); +``` + +### EAS Build Configuration + +```json +{ + "cli": { + "version": ">= 16.0.1", + "appVersionSource": "remote" + }, + "build": { + "production": { + "autoIncrement": true, + "ios": { + "resourceClass": "m-medium" + } + }, + "development": { + "developmentClient": true, + "distribution": "internal" + } + }, + "submit": { + "production": {} + } +} +``` + +### Testing & Type Checking + +```bash +# TypeScript +npx tsc --noEmit + +# Run tests +npm test + +# Lint +npx eslint . +``` + +### Key Takeaways + +1. **Start simple**: Always test in Expo Go before creating custom builds +2. **Follow conventions**: Use Expo Router patterns, kebab-case filenames +3. **Use modern APIs**: Prefer `expo-audio`, `expo-video`, `expo-image` +4. **Handle safe areas**: Use `contentInsetAdjustmentBehavior="automatic"` +5. **Style with CSS**: Use `boxShadow` instead of legacy shadow props +6. **Type everything**: Use TypeScript strict mode, no `any` +7. **Secure tokens**: Use `expo-secure-store` for sensitive data +8. **Environment config**: Use `EXPO_PUBLIC_` prefix for client env vars + +--- + +## 📝 Project Context + +**TabataFit** — "Apple Fitness+ for Tabata" + +- **Framework**: Expo SDK 52 (managed) +- **Navigation**: Expo Router v3 +- **State**: Zustand + AsyncStorage +- **Video**: expo-av → HLS streaming +- **Audio**: expo-av (coaching + music) +- **Animations**: React Native Animated +- **Payments**: RevenueCat +- **Analytics**: PostHog + +### Design System + +```typescript +BACKGROUND: '#000000' // Pure black +SURFACE: '#1C1C1E' // Charcoal +BRAND: '#FF6B35' // Flame orange +REST: '#5AC8FA' // Ice blue +SUCCESS: '#30D158' // Energy green +``` + +### Phase Colors (Critical) + +```typescript +PREP: '#FF9500' // Orange-yellow +WORK: '#FF6B35' // Flame orange +REST: '#5AC8FA' // Ice blue +COMPLETE: '#30D158' // Green +``` + +--- + +*Last updated: March 14, 2026*