Dev Blog #1: LiftWyse

November 18, 2024

When I go to the gym, I usually take mental notes on where I am in the workout and what the next few sets will look like. Despite doing that for years, I've gotten tired of digging through my head to remember the results of each set. Sure there are apps out there that solve this problem for me, but why not just build the answer yourself?


Inception

LiftWyse was first an app I would daydream about creating. It had an impressive list of features and even included a paid service that allows the user to track bar paths to optimize their form. It's easier said than done, but this vision would never be realized unless I took the first steps. After graduating and some well deserved R&R, I started designing on Figma and researching the best tech stack for my idea.

My initial mockups took about a week to do. I gave myself time to think about how I would want my features to look and feel from the user's perspective, focusing on a seamless user experience and having users input their workout data in as little clicks as possible. This perspective definitely affected the systems I would design then later use in the app.


Project Image
  Entire App mockup via Figma

If you noticed the beautifully crafted MSPaint mockups, these updated designs inspired me to incorporate "Tinder-Like" swipe gestures. Initially, users had to determine the result of their set on the same page where they entered the anticipated set weight and rep count. After consulting my QA engineer (my mom) multiple times to share updates, this workflow emerged as a significant pain point. The original process of adding workouts felt awkward, prompting me to redesign the flow with card - swiping mechanics to make logging workouts more seamless and efficient.

At this point, I have successfully implemented both the plan and workout pages on the frontend and the backend. While the UI of these pages slightly differs from the mockups, their functionality aligns perfectly with my vision. The plan page allows users to input their planned workouts for the day, while the lift page presents a stack of cards that displaying set information in FIFO order. Similar to dating apps like Tinder, a user can swipe left to indicate that their set was unsuccessful (eg. did not reach desired rep range) or right to mark it as successful. This intuitive card feature enables users to document their progress quickly and efficiencly thorughout their workout sessions.


About those screenshots...

"Why would he be writing a dev blog so early into development?" It's a valid point, and the reason for that is a bit more frustrating. During early development, I decided to use React Native with the tools that Expo Go provides. I chose Expo Go for multiple reasons, but the main ones were that Expo Go had a powerful CLI for development and I was working on a Windows machine while designing an app to be compatible with iOS.

Halfway into debugging some issues with the cards, Expo SDK updated to version 12 and made it to where accessing my app became impossible without updating installed modules. After going through the installation, I come to find out that the app I use to display my project on my phone doesn't support projects built on SDK 11. This issue still puzzles me because I had gone through the updating process yet Expo Go identifies my app as using version 11.

I'm disappointed in the lack of actual screenshots and am currently working to retrieving them! But if screenshots can't be shown, then this would be a great opportunity to delve into the codebase and showcase the systems running under the hood.


Logging Workouts

I wanted to gain exposure to working with a NoSQL database, and I chose Firebase as it matched the scale and needs of my project. Getting started with Firebase was challenging at first, especially as I relied heavily on GenAI tools to guide me through configuring the database. Along the way, I encountered multiple roadblocks, mainly because I didn't thoroughly test everything the AI suggested. One key takeaway from this experience is the importance of double-checking the answers provided by GenAI! Despite the challenges, I'm glad I used Firebase, as it gave me a better understanding of NoSQL databases. I now appreciate how Firebase allows for dynamic database design through custom reference paths, offering flexibility that contrasts with my experience using MySQL, where tables and relationships need to be explicitly defined in advance. Additionally, Firebase’s database API was straightforward to initialize and integrate, making it an effective choice for this project. I ended up abstracting my database queries into a single file called fbService.js. For logging workouts, I have a function addWorkout that takes user data, transforms that into a custom data object, and adds it into the database.


Project Image
  Function for adding workout

The idea here is that the data object is created to contain user data and their workout info. It is then transformed into a JSON object and sent to my database towards the dbRef that contains a respective user's workouts. I decided to export Firebase RDB functions from the config file since they would be reused a lot throughout the service script. Personally, I also think it looks nice and helps me with organizing my code.

Project Image
  workouts table of database

Overall, Firebase was fairly simple to use and extremely user friendly. Firebase's API documentation was very helpful and didn't feel awful to read. 10/10, will continue to use for other projects in the future!


Pick A Card

At first, implementing the card functionality sounded like a difficult thing to do. Thankfully, there were resources online that I was able to read and understand how I can tackle this problem. The first initial issue was how I would even display a stack of cards. I decided to abstract the card itself and create a component called liftCard.tsx. Then in the lift page, I would iterate through an array of card components each containing its respective set information. I used multiple different npm packages to facilitate this feature, including react-native-deck-swiper, react-native-gesture-handler, and react-native-reanimated.

Project Image
  HTML for displaying deck of cards

One challenge I faced was detecting whether a user swiped left or right. Initially, I considered recording the X position of the user’s finger from the start to the end of the swipe but wasn’t sure how to implement this approach effectively. After some research, I found a solution by leveraging the screen's width. By dividing the screen into two halves and comparing the ending X position of the swipe to the midpoint, I could reliably determine which side of the screen the swipe ended on. To handle the logic, I utilized runOnJS from the React Native Reanimated 2 library, enabling seamless execution of JavaScript functions within the workout page for a smooth user experience.

Project Image
  TS Function for handling swipe end

At this point, the cards were functional with triggers and animations! The next step was to develop the backend and connect it to the cards. A key component of this process was implementing the fetchWorkouts function, which is responsible for correctly populating the card stack in FIFO order. This is one of the reasons I chose Firebase; it makes querying and retrieving items in FIFO order straightforward. Instead of relying on incrementing IDs, I leveraged Firebase's natural ordering of entries within the Realtime Database. By iterating over the snapshot of workouts retrieved from the database, I dynamically pulled and structured each workout's data to populate the card stack. This approach ensures the workout entries are displayed in the correct sequence.

Project Image
  TS Function for fetching workouts

Now the card is populated with info! At this point, there isn't much to do with the cards other than swipe on them, but I intend on adding things like deleting from DB and adding notes to each set.

Onwards to new things (for now)

Due to my current goals and my increasing frustration towards debugging my tech stack, I decided to put this project on the backburner for now and pivot into learning to program a Raspberry Pi and studying for certs like CompTIA Network+. I'm still persistently looking for that entry level job to gain invaluable professional experience and I feel like this project was a stepping stone towards that goal! I look forward to going back into this project and continuing on development!

View Project