# Pitfalls: Workout App UX Improvements

**Project:** Gravl — PPL Workout Tracker
**Researched:** 2026-02-15

## Critical Pitfalls (Address in This Milestone)

### 1. Breaking Existing Logging Flow
- **Risk:** Custom exercises don't integrate with `program_exercise_id` FK; progression and history break
- **Warning signs:** Existing workout logs return empty after schema changes; progression graph gaps
- **Prevention:** Add `source_type` column with default 'program'; never modify existing FK relationships; custom workouts use separate `custom_workout_exercise_id`
- **Phase:** Database schema changes (early)

### 2. Competing State on Shared Program
- **Risk:** If users modify `program_exercises` directly, it affects ALL users sharing program_id=1
- **Warning signs:** One user's set count change appears for another user
- **Prevention:** Never modify program_exercises table for per-user changes. Custom modifications create a new custom_workout that forks from the program. Program data stays read-only
- **Phase:** Custom workout architecture

### 3. Backward Compatibility with Existing Logs
- **Risk:** Existing logs assume fixed sets; schema changes break progression graphs and workout history
- **Warning signs:** Historical workout data disappears or shows incorrectly
- **Prevention:** `source_type` defaults to 'program'; all existing queries continue unchanged; new queries handle both source types
- **Phase:** Database migration

### 4. Input Validation Gaps
- **Risk:** No validation on negative reps, extreme weights, or invalid set numbers
- **Warning signs:** Corrupted data in database; nonsensical progression suggestions
- **Prevention:** Frontend: `min=0` on inputs, stepper controls with bounds. Backend: validate before insert
- **Phase:** Input UX fixes (Phase 1)

### 5. Mobile Layout Breakage
- **Risk:** Extra buttons (add set, remove set, modify workout) break 600px layout; unusable on small phones
- **Warning signs:** Horizontal scroll appears; buttons overlap; touch targets too small
- **Prevention:** Design all new controls within existing 600px constraint first; test on 320px width; maintain 44px minimum touch targets
- **Phase:** All UI changes

### 6. Scope Creep from "Add Set" to Full Program Builder
- **Risk:** "Flexible sets" requirement grows into full periodization, program editor, template system
- **Warning signs:** Conversations about "what if users want to plan a whole week" or "program templates"
- **Prevention:** Strict scope: add/remove sets during a workout session. Custom workouts are simple exercise lists, not programs. No scheduling, no periodization
- **Phase:** Scope discipline throughout

### 7. Unclear Completion State
- **Risk:** Flexible sets make "workout complete" ambiguous — did they skip a set or just not add one?
- **Warning signs:** Users feel guilty about "incomplete" workouts; confusion about what counts as done
- **Prevention:** No "complete workout" enforcement. Each logged set is saved independently. Summary shows what was actually done, not what was "expected"
- **Phase:** Workout flow UI

## Gravl-Specific Risks

### Hardcoded program_id=1
Dashboard directly fetches `programs/1`. Custom workouts that aren't program-linked will need their own navigation path in WorkoutSelectPage.

### Upsert-Only Logging
Current `/api/logs` only updates/inserts. If user removes a set, there's no delete mechanism. Need DELETE endpoint for individual log entries.

### Component-Level State Loss
Logs stored in React useState, not localStorage. If app closes mid-workout, all unlogged progress is lost. Consider auto-saving to localStorage as draft.

### Single-File Backend
Adding new endpoints to `backend/src/index.js` (already 425 lines) increases risk of accidentally breaking existing routes. Test existing endpoints after each backend change.

## Pre-Shipping Checklist

- [ ] Existing workout logging still works identically
- [ ] Historical workout data displays correctly
- [ ] Progression suggestions unchanged for program workouts
- [ ] All inputs validate (no negative reps, no negative weight)
- [ ] Layout works on 320px-600px width range
- [ ] Custom workouts don't affect other users' program data
- [ ] Set add/remove persists correctly in database
