Josh Bruce Online

Hearts (6♥) - Fitness Tracker Documentation

Overview

Hearts is a comprehensive Progressive Web App (PWA) fitness tracking platform built with React. It provides workout logging, nutrition tracking, progress analytics, and goal management with a sophisticated iOS-inspired interface and Firebase backend integration.

Technical Architecture

Core Technologies

File Structure

hearts/
├── index.html                          # Main React application
├── manifest.json                       # PWA manifest configuration
├── sw.js                               # Service worker for offline functionality
├── 6hearts.jpeg                        # App icon and branding
├── firestore.rules                     # Firestore security rules
├── HEARTS_DOCUMENTATION.md             # Existing technical documentation
├── research.md                         # Fitness research and methodology
├── webapp_implementation_guide.json    # Implementation guidelines
├── workout-system-documentation.md     # Workout system architecture
├── master_program_coordinator.json     # Workout program coordination
├── weekly-workout-split.json           # Workout split configurations
└── [exercise_type]_exercises.json      # Exercise database files
    ├── arms_exercises.json
    ├── back_exercises.json
    ├── chest_exercises.json
    ├── core_exercises.json
    ├── shoulders_exercises.json
    └── forearm_exercise_database.json

Application Architecture

React Component Hierarchy

App
├── Header (stats display, timer)
├── TabBar (navigation system)
├── MainContent
   ├── WorkoutView
      ├── ExerciseSelector
      ├── SetTracker
      ├── RestTimer
      └── ProgressChart
   ├── NutritionView
      ├── CalorieCounter
      ├── MacroTracker
      ├── MealPlanner
      └── HydrationLog
   ├── ProgressView
      ├── WeightTracker
      ├── AnalyticsCharts
      ├── AchievementSystem
      └── DataExport
   └── SettingsView
       ├── UserProfile
       ├── Goals
       ├── Preferences
       └── DataManagement

PWA Implementation

Manifest Configuration

{
  "name": "6♥ - Fitness Tracker",
  "short_name": "Hearts",
  "description": "Your personal fitness tracking companion",
  "start_url": "/hearts/",
  "display": "standalone",
  "theme_color": "#60A5FA",
  "background_color": "#FAFAFA",
  "orientation": "portrait",
  "icons": [
    {
      "src": "6hearts.jpeg",
      "sizes": "152x152",
      "type": "image/jpeg",
      "purpose": "any maskable"
    }
  ]
}

Service Worker Features

// sw.js - Offline functionality
const CACHE_NAME = 'hearts-v1';
const urlsToCache = [
  '/hearts/',
  '/hearts/index.html',
  '/hearts/manifest.json',
  '/hearts/6hearts.jpeg'
];

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then((cache) => cache.addAll(urlsToCache))
  );
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then((response) => {
        return response || fetch(event.request);
      })
  );
});

iOS Integration

<!-- iOS-specific PWA features -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="6♥">
<link rel="apple-touch-icon" href="6hearts.jpeg">
<link rel="apple-touch-icon" sizes="152x152" href="6hearts.jpeg">
<link rel="apple-touch-icon" sizes="180x180" href="6hearts.jpeg">

<!-- iOS splash screens for different devices -->
<link rel="apple-touch-startup-image" 
      href="splash-2048x2732.png" 
      media="(device-width: 1024px) and (device-height: 1366px)">

Design System

CSS Custom Properties

:root {
  /* Base colors */
  --bg-primary: #FAFAFA;
  --bg-secondary: #FFFFFF;
  --bg-tertiary: #F3F4F6;
  --text-primary: #1D1D1F;
  --text-secondary: #6B7280;
  --text-tertiary: #9CA3AF;
  
  /* Accent colors */
  --accent-blue: #3B82F6;
  --accent-green: #10B981;
  --accent-purple: #8B5CF6;
  --accent-orange: #F59E0B;
  --accent-amber: #F78200;
  --accent-red: #EF4444;
  
  /* Border and shadow */
  --border-primary: #E5E7EB;
  --border-secondary: #F3F4F6;
  --shadow: rgba(0, 0, 0, 0.04);
  --shadow-hover: rgba(0, 0, 0, 0.08);
  --overlay: rgba(255, 255, 255, 0.98);
}

Typography System

/* iOS-inspired typography */
body {
  font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 
               Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-optical-sizing: auto;
}

Layout System

/* iOS safe area support */
body::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: env(safe-area-inset-top, 0px);
  background: var(--overlay);
  z-index: 101;
}

/* Header with backdrop blur */
.header {
  height: 6vh;
  background: var(--overlay);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-shadow: 0 1px 3px var(--shadow);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

/* Tab bar with safe area padding */
.tab-bar {
  height: 10vh;
  background: var(--overlay);
  backdrop-filter: blur(20px);
  padding: 20px 20px 40px 20px;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

Workout System

Exercise Database Structure

// Example: chest_exercises.json
{
  "exercises": [
    {
      "id": "bench_press",
      "name": "Bench Press",
      "muscle_groups": ["chest", "triceps", "shoulders"],
      "equipment": ["barbell", "bench"],
      "difficulty": "intermediate",
      "instructions": [
        "Lie flat on bench with feet firmly on ground",
        "Grip barbell with hands wider than shoulder-width",
        "Lower bar to chest with control",
        "Press bar up explosively"
      ],
      "tips": [
        "Keep shoulder blades retracted",
        "Maintain natural arch in lower back",
        "Don't bounce bar off chest"
      ],
      "variations": [
        "Incline Bench Press",
        "Decline Bench Press",
        "Dumbbell Bench Press"
      ]
    }
  ]
}

Workout Tracking

// Workout session structure
const workoutSession = {
  id: generateId(),
  date: new Date().toISOString(),
  startTime: Date.now(),
  endTime: null,
  exercises: [
    {
      exerciseId: 'bench_press',
      sets: [
        {
          reps: 10,
          weight: 185,
          restTime: 120, // seconds
          completed: true,
          notes: 'Felt strong today'
        }
      ]
    }
  ],
  totalVolume: 0, // calculated
  duration: 0, // calculated
  notes: 'Great chest workout'
};

Program Coordination

// master_program_coordinator.json
{
  "programs": {
    "push_pull_legs": {
      "name": "Push/Pull/Legs Split",
      "frequency": 6,
      "days": {
        "push": {
          "muscle_groups": ["chest", "shoulders", "triceps"],
          "exercises": ["bench_press", "shoulder_press", "tricep_dips"]
        },
        "pull": {
          "muscle_groups": ["back", "biceps"],
          "exercises": ["pull_ups", "rows", "bicep_curls"]
        },
        "legs": {
          "muscle_groups": ["quads", "hamstrings", "glutes"],
          "exercises": ["squats", "deadlifts", "lunges"]
        }
      }
    }
  }
}

Nutrition Tracking

Calorie Management

// Nutrition tracking system
const nutritionEntry = {
  id: generateId(),
  date: new Date().toISOString(),
  meals: [
    {
      type: 'breakfast',
      foods: [
        {
          name: 'Oatmeal',
          calories: 150,
          macros: {
            protein: 5,
            carbs: 27,
            fat: 3
          },
          quantity: 1,
          unit: 'cup'
        }
      ]
    }
  ],
  totalCalories: 0, // calculated
  totalMacros: {
    protein: 0,
    carbs: 0,
    fat: 0
  },
  waterIntake: 0, // ml
  goals: {
    calories: 2200,
    protein: 165,
    carbs: 275,
    fat: 73
  }
};

Macro Tracking

// Macro calculation and visualization
function calculateMacroPercentages(macros, totalCalories) {
  const proteinCals = macros.protein * 4;
  const carbCals = macros.carbs * 4;
  const fatCals = macros.fat * 9;
  
  return {
    protein: (proteinCals / totalCalories) * 100,
    carbs: (carbCals / totalCalories) * 100,
    fat: (fatCals / totalCalories) * 100
  };
}

Progress Analytics

Data Visualization

// Chart.js integration for progress tracking
const progressChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: dates,
    datasets: [{
      label: 'Weight Progress',
      data: weightData,
      borderColor: 'var(--accent-blue)',
      backgroundColor: 'rgba(59, 130, 246, 0.1)',
      tension: 0.4
    }]
  },
  options: {
    responsive: true,
    plugins: {
      legend: {
        display: false
      }
    },
    scales: {
      y: {
        beginAtZero: false,
        grid: {
          color: 'var(--border-secondary)'
        }
      }
    }
  }
});

Achievement System

// Achievement tracking
const achievements = {
  'first_workout': {
    name: 'First Steps',
    description: 'Complete your first workout',
    icon: '🏃‍♂️',
    unlocked: false
  },
  'week_streak': {
    name: 'Week Warrior',
    description: 'Work out 7 days in a row',
    icon: '🔥',
    unlocked: false
  },
  'pr_bench': {
    name: 'Bench Beast',
    description: 'Set a new bench press PR',
    icon: '💪',
    unlocked: false
  }
};

Firebase Integration

Firestore Structure

// Data organization in Firestore
users/{userId}/
├── profile/
   ├── name: string
   ├── email: string
   ├── age: number
   ├── height: number
   ├── currentWeight: number
   └── goals: object
├── workouts/{workoutId}/   ├── date: timestamp
   ├── exercises: array
   ├── duration: number
   └── notes: string
├── nutrition/{dateString}/   ├── meals: array
   ├── totalCalories: number
   ├── macros: object
   └── waterIntake: number
└── progress/{dateString}/
    ├── weight: number
    ├── bodyFat: number
    ├── measurements: object
    └── photos: array

Security Rules

// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
      
      match /workouts/{workoutId} {
        allow read, write: if request.auth != null && request.auth.uid == userId;
      }
      
      match /nutrition/{date} {
        allow read, write: if request.auth != null && request.auth.uid == userId;
      }
      
      match /progress/{date} {
        allow read, write: if request.auth != null && request.auth.uid == userId;
      }
    }
  }
}

Performance Optimizations

React Optimizations

// Memoized components for performance
const WorkoutExercise = React.memo(({ exercise, onUpdate }) => {
  const [sets, setSets] = React.useState(exercise.sets);
  
  const handleSetUpdate = React.useCallback((setIndex, updates) => {
    setSets(prev => prev.map((set, index) => 
      index === setIndex ? { ...set, ...updates } : set
    ));
  }, []);
  
  return (
    <div className="exercise-container">
      {/* Exercise UI */}
    </div>
  );
});

Data Caching

// Efficient data caching strategy
const useWorkoutData = (userId) => {
  const [workouts, setWorkouts] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  
  React.useEffect(() => {
    const unsubscribe = firebase.firestore()
      .collection('users')
      .doc(userId)
      .collection('workouts')
      .orderBy('date', 'desc')
      .limit(50)
      .onSnapshot((snapshot) => {
        const workoutData = snapshot.docs.map(doc => ({
          id: doc.id,
          ...doc.data()
        }));
        setWorkouts(workoutData);
        setLoading(false);
      });
    
    return unsubscribe;
  }, [userId]);
  
  return { workouts, loading };
};

Mobile Optimization

Touch Interactions

/* Optimized touch targets */
.touch-target {
  min-height: 44px;
  min-width: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
}

/* Smooth scrolling */
.scrollable-area {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scroll-behavior: smooth;
}

Responsive Breakpoints

/* Mobile-first responsive design */
@media (max-width: 640px) {
  .input-area {
    width: 90vw;
  }
  
  .story-words.full-story {
    height: calc(100vh - 60px);
    padding: 20px;
    font-size: 1em;
  }
}

/* Larger screens */
@media (min-width: 1024px) {
  .input-area {
    max-width: min(70vw, 900px);
  }
}

Accessibility Features

Keyboard Navigation

// Comprehensive keyboard support
document.addEventListener('keydown', (e) => {
  if (e.key === 'Tab') {
    // Focus management
    handleTabNavigation(e);
  } else if (e.key === 'Enter' || e.key === ' ') {
    // Action activation
    handleActionKeys(e);
  } else if (e.key === 'Escape') {
    // Modal dismissal
    handleEscapeKey(e);
  }
});

Screen Reader Support

<!-- ARIA labels and roles -->
<button aria-label="Add new set" 
        aria-describedby="set-help-text"
        role="button">
  +
</button>

<div id="set-help-text" className="sr-only">
  Click to add a new set to this exercise
</div>

Data Export and Backup

Export Functionality

// Data export to various formats
function exportWorkoutData(format = 'json') {
  const data = {
    exportDate: new Date().toISOString(),
    user: userProfile,
    workouts: allWorkouts,
    nutrition: nutritionData,
    progress: progressData
  };
  
  switch (format) {
    case 'json':
      return JSON.stringify(data, null, 2);
    case 'csv':
      return convertToCSV(data);
    case 'pdf':
      return generatePDF(data);
    default:
      return data;
  }
}

Error Handling

Comprehensive Error Management

// Error boundary for React components
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  
  componentDidCatch(error, errorInfo) {
    console.error('Hearts app error:', error, errorInfo);
    // Log to error reporting service
  }
  
  render() {
    if (this.state.hasError) {
      return (
        <div className="error-fallback">
          <h2>Something went wrong</h2>
          <button onClick={() => window.location.reload()}>
            Reload app
          </button>
        </div>
      );
    }
    
    return this.props.children;
  }
}

Future Enhancements

Planned Features

  1. Social Features: Workout sharing and challenges
  2. AI Coaching: Personalized workout recommendations
  3. Wearable Integration: Apple Watch and Fitbit sync
  4. Video Tutorials: Exercise demonstration videos
  5. Meal Planning: AI-powered nutrition planning

Technical Improvements

  1. TypeScript: Type safety and better development experience
  2. Testing: Comprehensive unit and integration tests
  3. Performance: Further optimization and code splitting
  4. Offline Mode: Enhanced offline functionality
  5. Real-time Sync: Multi-device synchronization

Conclusion

Hearts represents a sophisticated fitness tracking platform that combines modern web technologies with thoughtful user experience design. The React-based architecture provides flexibility and performance, while the PWA features ensure accessibility across all devices. The comprehensive exercise database and nutrition tracking make it a complete fitness companion.

Technical Rating: 9.3/10