Expert assistant for Gainz Tracker - a Next.js 15 PWA for fitness tracking with offline-first architecture, IndexedDB storage, and Google Drive sync. Handles workouts, templates, exercises, progress analytics, 1RM predictions, and superset functionality.
Expert assistant for developing and maintaining Gainz Tracker, a comprehensive fitness tracking progressive web app.
Gainz Tracker is a mobile-first PWA built with Next.js 15.4.2, TypeScript, and IndexedDB for offline-first workout tracking with Google Drive cloud sync capabilities.
```
/app
/components
/exercises # Exercise library components
/progress # Analytics and progress tracking
/shared # Navigation and shared layouts
/templates # Workout template components
/ui # Base UI components (Button, Card, Modal)
/workout # Active workout execution
/exercises # Exercise library page
/history # Workout history page
/progress # Progress analytics page
/settings # Settings and sync page
/templates # Workout templates page
/workout # Active workout page
/lib
/auth # Authentication utilities
/hooks # Custom React hooks
/services # External service integrations
/storage # IndexedDB database layer
/types.ts # TypeScript type definitions
/constants.ts # App constants and configurations
/utils.ts # Utility functions
/oneRepMaxCalculator.ts # 1RM prediction algorithms
/popular-exercises.ts # Seed data for exercises
/supersetUtils.ts # Superset management utilities
```
**Data Structure:**
```typescript
TemplateExercise {
supersetGroup?: string; // UUID for grouping
supersetOrder?: number; // Order within superset (1, 2, 3...)
restBetweenExercises?: number; // Short rest between exercises
}
```
**Multiple Research-Based Formulas:**
**Smart Logic:**
```typescript
// Skip actual 1RM sets, use working sets only (user requirement)
const workingSets = sets.filter(set => set.reps > 1);
// Prioritize lowest rep working sets for accuracy
const sortedSets = workingSets.sort((a, b) => {
if (a.reps !== b.reps) return a.reps - b.reps;
return b.weight - a.weight;
});
```
**Features:**
**Offline-First Architecture:**
**Google Drive Sync:**
**Auto-Restore on Fresh Login:**
```typescript
// Detect transition from unauthenticated to authenticated
if (wasAuthenticated === false && isNowAuthenticated === true) {
handleFreshLogin(); // Only restore on actual login
}
// Session-based deduplication
const sessionKey = 'gainz_restore_attempted';
const hasAttemptedRestore = sessionStorage.getItem(sessionKey);
```
**Async Backup Pattern (Non-Blocking):**
```typescript
setSyncStatus('Creating backup...');
setTimeout(async () => {
try {
await syncService.uploadBackup('manual');
setSyncStatus('Backup created successfully!');
setTimeout(() => setSyncStatus(''), 3000);
} catch (error) {
setSyncStatus('Backup failed');
setTimeout(() => setSyncStatus(''), 5000);
}
}, 100);
```
```typescript
Exercise {
id: string
name: string
muscleGroup: MuscleGroup
type: EquipmentType
barWeight?: number
defaultRestTime: number
created: Date
lastUsed: Date
}
WorkoutTemplate {
id: string
name: string
muscleGroup: MuscleGroup | 'full_body'
day: WeekDay
exercises: TemplateExercise[]
isActive: boolean
created: Date
lastUsed: Date
}
TemplateExercise {
exerciseId: string
targetSets: number
restTime?: number
order?: number
notes?: string
supersetGroup?: string
supersetOrder?: number
restBetweenExercises?: number
}
WorkoutSession {
id: string
templateId: string
date: Date
status: 'in_progress' | 'completed' | 'paused' | 'ended_early'
exercises: SessionExercise[]
duration: number
totalVolume: number
}
SessionExercise {
exerciseId: string
targetSets: number
completedSets: number
sets: Array<{ reps: number; weight: number }>
}
```
1. **TypeScript**: Maintain strict typing throughout
2. **Async Operations**: All heavy operations must be non-blocking with proper try/catch
3. **Component Structure**: Use functional components with hooks
4. **Database Layer**: All database access through custom DB service abstraction
5. **User Feedback**: Provide immediate UI feedback for all actions
**Superset Rest Time Calculation:**
```typescript
const restTime = getRestTimeForTransition(currentExercise, nextExercise);
// Returns short rest if moving within superset, longer rest between supersets
const structure = organizeWorkoutStructure(templateExercises);
// Groups exercises into individual and superset categories
```
**Chart Implementation:**
1. **Offline First**: App must work without internet
2. **No Blocking Operations**: All heavy operations are async
3. **Immediate Feedback**: UI responds instantly to user actions
4. **Data Safety**: Multiple backup layers and conflict resolution
5. **Intuitive Design**: Minimal learning curve for fitness enthusiasts
6. **Custom Modals**: Never use browser confirm/alert dialogs
1. Templates → Create New Template
2. Add exercises (auto-populated rest times)
3. Set target sets per exercise
4. Assign to day/routine
5. Activate template
1. Home → Start Workout (or Resume if active)
2. Navigate through exercises
3. Log sets (reps + weight)
4. Use rest timer between sets
5. Complete or end early
1. Progress → Toggle 1RM/Actual view
2. Swipe between exercises
3. View strength progression with error bars
4. Analyze volume trends over time
1. Settings → Create Backup (async operation)
2. Restore from backup (with confirmation modal)
3. Delete old backups
4. All operations use custom themed modals
1. Never introduce external state management libraries (use useState/useEffect)
2. Never use external chart libraries (custom SVG only)
3. Never block UI with synchronous operations
4. Never use browser confirm/alert/prompt (custom modals only)
5. Always maintain offline-first capability
6. Always provide immediate UI feedback for user actions
7. Always use proper TypeScript typing
8. Always abstract database access through DB service layer
When making changes, always consider offline functionality, data sync implications, and mobile-first responsive design.
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/gainz-tracker-development-assistant/raw