Creating a Workout App with Monaca and Capacitor

Juan Serrano Soria
The Web Tub
Published in
9 min readFeb 26, 2024

In this article we will learn how to create an application that will serve as our fitness companion. From tracking your weight and BMI to generating a workout routine that adapts to your needs, searching new exercises and learning how to perform them, and adding the workouts to your personal calendar.

Technologies used

Prerequisites

Setting up the project

Once all prerequisites are installed, open a terminal and create a new Monaca project using the Capacitor Basic template, as follows:

Alternatively you can do it from Monaca Cloud IDE, in the same way.

Since this template does not include any framework, the next step is to add React to the project.

The generated structure of the project is the following:

The code developed for the app will be inside of /src.

The next step is to create a Firebase project. To do so a google account is needed. Go to Firebase console and create a new project, giving it the desired name, id and accepting terms and conditions.

After the project is created, register an application (client) as Web Application in Firebase console. This way all firebase information is obtained, mainly the firebaseConfig, which looks like this:

The next step is to enable authentication, in this case with email and password.

After that, the last thing needed is to initialize Firestore.

Remember to set up proper rules for Firestore, so the information is only accessible to authenticated users, for example:

If you want to build locally, make sure Android Studio and Xcode are installed and working, and the pertinent simulators work.

Development

First, we install the required libraries, using yarn

All the dependencies used are the following, which are divided into:

  • Capacitor related dependencies, already installed after setting up the project with Monaca
  • React related libraries, to use the popular web framework
  • Firebase library, to interact with Authentication and Firestore
  • Material UI related dependencies, a powerful react UI library
  • Capacitor Calendar Plugin, to access the native calendar application

To use the Calendar plugin, we have to add the following line to config.yaml for it to work on iOS.

First things first, since we are using a hybrid framework, the purpose of the app is to work in web, android and iOS seamlessly. In order to do so, we will apply the following styling to the body of the html.

This will avoid running into problems with different devices’ screens. We will come back to this later as it does not solve all the styling problems for iOS, but for now, since we are using Material UI, these will be the only contents in our style.css file.

To work with Firebase we create a file with all the configuration needed, and export our Firestore database and authentication objects. We will need these so the user can log in, and to read and write user’s information throughout the application.

We have all environment variables in a configuration file. If they are not set, a message is displayed for the user referring to where they should add them.

This is standard firebase usage, but note that there is an important fix for iOS from line 46.

After the setup is completed then we proceed to create the different screens of the application:

The application is divided into 4 main screens, plus 2 screens to handle login and signup. There is also an error screen. Both light and dark themes are implemented throughout the main screens. There is also a drawer element to navigate between them.

Login and Signup

For these two screens, the main functionality to take into consideration is the usage of Firebase authentication and Firebase firestore, for authenticating and retrieving user data respectively.

Also, since the urls for the animations of the exercises provided by the API used will change once every 24 hours, we use login to refetch these, as to avoid having blank images displayed.

Dashboard

The Dashboard screen contains a grid with different cards on it:

  1. A weight chart that displays the last 6 recorded weights of the user, and the ideal weight for their height

2. A BMI gauge chart

3. An overview of the workout routine of the user, consisting of the exercises that they should perform each day of the routine

This screen only displays information, so there is no interaction with Firebase.

Profile

In this screen the user can check their personal and fitness information, including the numerical value of their BMI. The user can change these details, so there are write operations performed against Firestore database. The state of the application is also updated so the user can see new information across screens.

For example, for updating height and weight, the following code is used.

Routine

This screen displays the workout routine of the user. Each day contains a carousel of the different exercises programmed for that day. You can also check the instructions by opening a modal window.

If the user has not generated a workout routine yet, the app will prompt them to do so, by displaying a form with different parameters such as number of days available, workout duration and different goals. Once the form is completed the app will call the API to get different information about the exercises selected. Since this process takes some time, a loading indication is displayed on screen until it is finished.

Also, we integrated the Capacitor Calendar plugin in this screen, allowing the user to create an event with each workout day in their personal calendar.

Search exercises

This page allows the user to look for new exercises by name and other filters. The main functionality of this screen is to call the exercises API and filter the results according to the user’s input. In the same way as the previous screen, there is also the possibility to open a modal to display instructions for the selected exercise.

Error

This page is displayed when an error has occurred with RapidAPI ExerciseDB. The main reason is that the monthly usage limit has been reached.

Drawer and Bar

For the drawer element we choose a Material UI component that allows the user to swipe the screen to open and close it, since the purpose of the project is to be run on mobile devices.

For the top bar we include a button that toggles between light and dark mode. Again, since we are using Material UI, theming is straightforward.

There is one important consideration to make here. In our css we have taken into consideration the safe area, but these two Material UI components override this, which produces a styling error in iOS:

The content is pushed down inside of the safe area, but the Bar remains on top, hidden under iOS status bar. To fix this we have to apply styling directly inside of the Material UI component, as the following code.

Running the application

To run the application you can open a terminal inside of the project’s directory and run the following command:

This will open a local server with the web version of the project running.

If you want to test the application on Android or iOS, you can either use Monaca Cloud IDE to build on the cloud or set up the local environment.

If you’re using Monaca Cloud IDE, go to your project and select build for your target device.

If you’re building locally, you need to first generate the android and/or iOS projects with the following command, changing ios to android depending on your target.

Every time you make some changes to the project, run the following command:

After that you can open the project on Xcode or Android studio to build the application and run it in a simulator:

Conclusion

In this article we have shown how easy it is to create a hybrid application with Monaca and Capacitor that integrates services such as Firebase and a plugin to open the native calendar.

You can find the code for this project here.

Thanks for reading :)

--

--