Muscle Mission

A single-page fitness tracking app built with JavaScript and Node.js

Project type: Full-Stack Web Application (SPA)
Role: Full-Stack Developer
Tools: JavaScript, Node.js, Express.js, Balsamiq, HTML/CSS, LocalStorage
Duration: Q1 2024

Muscle Mission Demo

The Problem Statement

Many gym-goers struggle to track their workouts consistently, often relying on scattered notes, memory, or multiple apps that are overly complex and require logins or subscriptions.

Without a simple way to record exercise selections, weights, reps, and workout duration, users find it difficult to monitor progress over time. This leads to plateaus, ineffective training routines, and a lack of motivation.

Existing fitness apps also lack real-time responsiveness, and many do not allow users to quickly adjust or customise their routines during a session, creating unnecessary friction in the gym environment.

There is a need for a lightweight, fast, and user-friendly solution that enables fitness enthusiasts to track their workouts with zero setup, real-time interaction, and offline-friendly data persistence.

Muscle Mission Application

A comprehensive workout tracking application designed to support real-time features and persistent data storage for seamless user tracking

Workout naming interface

Custom Workout Naming

Users can personalize their workout sessions by naming each workout, creating a more organized and meaningful training experience.

Workout management interface

Complete Workout Management

Full control over workout sessions including adding exercises, canceling workouts, and finishing sessions with comprehensive tracking.

Workout stopwatch timer

Real-time Workout Timer

Integrated stopwatch functionality allows users to track the exact duration of their workouts, helping with pace and time management.

Workout history display

Persistent Workout History

All workout sessions are stored locally and remain accessible even after page refresh, providing a reliable training history log.

Workout rating interface

4-Star Rating System

Users can rate their workout sessions on a 4-star scale, allowing for quick assessment and tracking of workout quality over time.

Exercise completion checkboxes

Set-by-Set Completion Tracking

Checkbox system for marking individual sets as completed, providing granular control over exercise progress tracking.

Exercise selection popup

Overlay Exercise Selection

Clean popup interface for selecting exercises to add to workouts, with intuitive navigation and visual feedback.

Exercise management controls

Advanced Exercise Controls

Comprehensive exercise management including adding/removing sets and deleting exercises, giving users full flexibility in workout customization.

Mobile Wireframes

Designed around a strict single-column flow, each session phase — naming, tracking, and rating — is presented on its own focused screen, prioritising zero friction and one-handed usability in a gym environment.

Navigation

A persistent nav bar with thumbnail shortcuts keeps the workout page and history one tap away at all times.

Exercise Selection

Muscle group thumbnails let users scan and select exercises visually, reducing decision time mid-session.

Session Tracking

Auto-started stopwatch, set/weight/rep inputs, and a session rating are all surfaced as primary actions — no buried menus.

Workout History

Completed sessions are grouped with total time, weight lifted, date, and per-exercise sets for a clear progress snapshot.

Muscle Mission mobile wireframes created in Balsamiq

Desktop Wireframes

The desktop layout transforms the single-column mobile flow into a side-by-side session management view, reducing navigation friction and enabling the entire workout to be viewed at once.

Two-Panel View

The active exercise list and selection library sit side by side, removing the need to leave the current screen to add exercises.

Visual Selection

Exercise thumbnails in a grid format make browsing fast and intentional, matching the visual scanning pattern users expect.

Set Tracking

Sets, weights, and reps render in a table layout that scales cleanly across multiple exercises without collapsing into a list.

History Layout

Multi-column session summaries display full exercise breakdowns inline, making progress comparison across sessions natural.

Muscle Mission desktop wireframes created in Balsamiq

User Flow

The user flow maps the end-to-end journey from app entry to session review. Each decision point is designed to be shallow and reversible, keeping users focused on their workout instead of interface navigation.

Flow Clarity

A linear progression — home → name session → add exercises → track sets → finish — keeps users oriented at every step without requiring instructions.

Decision Points

Users choose muscle group, then exercise, then set count — each choice scoped to a single screen so the decision space never feels overwhelming.

Feedback Loops

Live stopwatch, set completion indicators, and an end-of-session rating give users continuous feedback that their progress is being captured.

Flexibility

Cancel workout, remove exercises, and delete history entries are available at every relevant stage — reducing anxiety about making a wrong choice.

Muscle Mission user flow diagram created in Balsamiq

Technical Implementation

Architecture Overview

Muscle Mission follows a modern Single Page Application (SPA) architecture with client-side rendering, persistent local storage, and a clean separation of concerns between UI, state management, and data persistence.

💻

Frontend Layer

HTML5
CSS3
JavaScript (ES6+)
LocalStorage API
⚙️

State Management

DOM Manipulation
Event Handling
Real-time Updates
Data Validation
💾

Data Layer

LocalStorage
JSON Serialization
CRUD Operations
Data Persistence

Frontend Implementation

🏗️

SPA Structure

  • Single HTML file with dynamic content rendering
  • Modular JavaScript for separation of concerns
  • No page reloads - all interactions handled client-side
  • Progressive enhancement for better user experience
🎨

Dynamic DOM Rendering

  • Template-based element creation
  • Real-time UI updates based on state changes
  • Efficient DOM manipulation with minimal reflows
  • Event delegation for better performance

Star-Rating Logic

  • Interactive 4-star rating system
  • Visual feedback on hover and selection
  • Persistent rating storage per workout
  • Average rating calculations for history
⏱️

Timer Logic

  • JavaScript Interval-based stopwatch
  • Start, pause, and reset functionality
  • Formatted time display (MM:SS)
  • Persistent timer state across sessions
💾

LocalStorage Structure

  • Structured JSON data storage
  • Workout history with timestamps
  • Exercise library persistence
  • Automatic data backup and recovery
📝

Form Handling

  • Real-time form validation
  • Dynamic form generation for exercises
  • Error handling and user feedback
  • Preventive measures against data loss

Data Flow & Storage

1

User Interaction

User creates workout, adds exercises, sets, and ratings

2

State Update

JavaScript updates application state and triggers UI re-render

3

Data Serialization

State data converted to JSON format for storage

4

Local Persistence

JSON data saved to browser's LocalStorage API

5

Session Recovery

Data loaded from LocalStorage on page reload/refresh

Key Code Implementation

LocalStorage Management

JavaScript
// Workout data persistence
    const WorkoutStorage = {
    saveWorkout: (workoutData) => {
        const workouts = JSON.parse(localStorage.getItem('workouts')) || [];
        workouts.push({...workoutData, timestamp: Date.now()});
        localStorage.setItem('workouts', JSON.stringify(workouts));
    },
    
    getWorkouts: () => {
        return JSON.parse(localStorage.getItem('workouts')) || [];
    },
    
    clearWorkout: (workoutId) => {
        const workouts = this.getWorkouts();
        const updated = workouts.filter(w => w.id !== workoutId);
        localStorage.setItem('workouts', JSON.stringify(updated));
    }
    };

Star Rating Component

JavaScript
// Interactive star rating system
    class StarRating {
    constructor(container, initialRating = 0) {
        this.rating = initialRating;
        this.stars = [];
        this.container = container;
        this.init();
    }
    
    init() {
        for (let i = 1; i <= 4; i++) {
        const star = document.createElement('span');
        star.className = 'star';
        star.dataset.value = i;
        star.textContent = '★';
        star.addEventListener('click', () => this.setRating(i));
        star.addEventListener('mouseover', () => this.hoverRating(i));
        this.stars.push(star);
        this.container.appendChild(star);
        }
    }
    
    setRating(value) {
        this.rating = value;
        this.updateDisplay();
        this.onRatingChange?.(value);
    }
    }

Timer Implementation

JavaScript
// Workout stopwatch timer
    class WorkoutTimer {
    constructor() {
        this.startTime = 0;
        this.elapsedTime = 0;
        this.timerInterval = null;
        this.isRunning = false;
    }
    
    start() {
        if (!this.isRunning) {
        this.startTime = Date.now() - this.elapsedTime;
        this.timerInterval = setInterval(() => this.update(), 1000);
        this.isRunning = true;
        }
    }
    
    pause() {
        if (this.isRunning) {
        clearInterval(this.timerInterval);
        this.isRunning = false;
        }
    }
    
    update() {
        this.elapsedTime = Date.now() - this.startTime;
        const seconds = Math.floor((this.elapsedTime / 1000) % 60);
        const minutes = Math.floor((this.elapsedTime / (1000 * 60)) % 60);
        return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    }
    }

Technical Challenges & Solutions

Challenge

Data Persistence Across Sessions

Workout data needed to survive browser refreshes and session changes.

Solution

Implemented robust LocalStorage management with JSON serialization, including error handling for storage limits and data corruption.

Challenge

Real-time UI Updates

Multiple UI elements needed to update simultaneously without performance issues.

Solution

Used event delegation and batched DOM updates to minimize reflows and repaints, ensuring smooth performance.

Challenge

Complex State Management

Managing nested workout, exercise, and set data with real-time validation.

Solution

Created a centralized state management system with immutability patterns and comprehensive validation at each level.