Inspiration

While working out at the gym, I wanted to listen to a podcast without losing track of my reps and sets. Counting manually while focusing on audio was distracting, so I wondered: what if an app could count reps and guide form automatically?

Since I had prior experience with MediaPipe, I decided to build GymSense—an AI-powered fitness companion that uses the camera to track exercise movements, count reps, and provide real-time form feedback.

What it does

GymSense helps users stay consistent and train with better form.

  • Choose a goal: Weight Gain, Weight Loss, or Custom Plan
  • Follow structured Day 1, Day 2, and Day 3 workout plans
  • Unlock the next day only after completing the previous one
  • Use MediaPipe pose tracking to count reps for exercises such as squats, push-ups, and jumping jacks
  • Receive real-time cues such as “Go a little slower” or “Keep your back straighter”
  • Track diet preferences, workouts, runs, friends, and streaks
  • Add friends through a request-and-accept flow, similar to LinkedIn connections
  • View a GitHub-style activity graph that visualizes workout consistency

How we built it

GymSense is built with Next.js, TypeScript, Tailwind CSS, Firebase Authentication, and Cloud Firestore.

The app uses MediaPipe Pose Landmarker in the browser to detect body landmarks such as shoulders, elbows, wrists, hips, knees, and ankles. It calculates joint angles and counts a repetition only after a complete movement cycle.

For example, a squat is counted when the knee angle drops below a “down” threshold and then rises above an “up” threshold:

$$ \theta_{\text{knee}} < \theta_{\text{down}} \quad \text{then} \quad \theta_{\text{knee}} > \theta_{\text{up}} $$

Firebase stores user profiles, workout progress, exercise logs, diet preferences, runs, friend requests, friendships, and streak data. Firestore security rules ensure that users can access and modify only their own data.

Challenges we ran into

The biggest challenge was making rep counting accurate. Simple angle thresholds were not enough because users move at different speeds and distances from the camera. I solved this by combining joint-angle thresholds with movement-state tracking and minimum rep-duration checks.

Designing the friend system was another challenge. Instead of allowing users to add friends directly, I implemented a request-and-accept flow. A user sends a request, the other user accepts or declines it, and only then are they connected as friends. Firestore rules prevent users from creating or modifying unauthorized friend requests.

Integrating Firebase securely was also challenging. I had to ensure that authentication, Firestore permissions, route protection, and user-specific data worked together without exposing private information.

Accomplishments that we're proud of

  • Built a working camera-based rep counter using MediaPipe
  • Created structured workout plans with day-by-day progression
  • Implemented secure Firebase Authentication and Cloud Firestore data storage
  • Designed a real request-and-accept friend system
  • Added a GitHub-style activity graph and streak tracking
  • Built a clean, mobile-first, sporty user interface

What I learned

This was my first project using Firebase, so I learned how to integrate Firebase Authentication and Cloud Firestore into a full-stack web app. I learned how to structure Firestore collections, manage authentication state, and write security rules that protect user data.

I also learned about:

  • MediaPipe pose estimation and landmark detection
  • Converting body landmarks into joint angles
  • Building reliable rep-counting logic
  • Designing workout progression and streak systems
  • Creating secure social features
  • Handling real-world camera and pose-detection issues

What's next for GymSense

Next, I plan to expand the exercise library, improve form analysis, add personalized workout progression, support more Bluetooth treadmills, and introduce live virtual running tracks with friends.

Built With

Share this project:

Updates

Submission history