So, I recently got into running and picked up a bargain Garmin watch. I looked on the marketplace for a simple watch face that had the attributes I wanted. I found nothing that suited my needs.
The apps from the app store were often too complex looking or lacked functionality.
This is where I started researching how to create a custom watch face and maybe even post it to the marketplace if possible. I learnt that Garmin uses Monkey C along with their SDK to create everything from watch faces to apps.
First things first, you need to setup the environment and download the SDK: https://developer.garmin.com/connect-iq/sdk/
Once setup, lets open Visual Studio Code and open the command palette using Ctrl+Alt+P. In this prompt, we want to search for the Monkey C: New Project option. It will then ask for the name of the project and the type. For this example, I will select a Simple Watch Face and set the API level to the lowest value.
This will build the project structure and create a base watch face to work from.
We now need to add supported products to the project. My watch is the Garmin Forerunner 735XT but you can use whichever watch you have. Use the command palette again and use the Monkey C: Edit Products option. In that dropdown, select all the watches you want to support and build for.
Now we can hit F5 and run the watch face in the virtual watch:

In this post, I’m going to build a watch face similar to the below design:

First, lets edit the layout.xml to build the design of the watch face. This file is in Resources -> Layouts.
Remove the default label from the XML file and lets build the 4 new labels required for our battery percentage, steps, current time and todays date.
The layouts are fairly easy to follow, each label requires the following attributes:
Attribute | Explanation | Possible Values |
id | The name of the label. This will be used in the code to update the value. | Any string value starting with a capital letter. E.g. TestLabel |
x | The horizontal positioning of the label. This can be a pixel value or the predefined values. | left, center, right, pixel value, or a percentage |
y | The vertical positioning of the label. This can be a pixel value or the predefined values. | top, center, bottom, pixel value, or a percentage |
font | The font to use on the label. These are predefined. | All options are documented in the API docs. We are only using values from API level 1.0.0 for now: https://developer.garmin.com/connect-iq/api-docs/Toybox/Graphics.html |
justification | How the text should position itself in the space provided. | TEXT_JUSTIFY_RIGHT, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_LEFT, TEXT_JUSTIFY_VCENTER |
color | The colour of the text | All options are documented in the API docs: https://developer.garmin.com/connect-iq/api-docs/Toybox/Graphics.html |
So my new layout.xml file will look like this:
Now that the layout is built, we need to build the functionality in the backend to update the view. Open the watch face _View.mc file. This can be found in Source -> watchface_View.mc.
First, lets add a required using statement at the top. Add the following line:
using Toybox.Time.Gregorian as Calendar;
I will also create a new method for updating the view. This method will take in the string ID of the label as well as the new value:
We can now use the above method to update the view.
We will now head over to the onUpdate method to update the view.
Now, lets work on building the required data and formatting it before updating the view. You can see below how I work through each of the four required sections and use the above updateDisplayObject method to update the view:
Now, when we hit F5 to run the watch face, you can see how the display has changed and we have built the watch layout:

Hope this helps someone out as the documentation is a little lacking. Enjoy! 🎉 🎉
Additional Notes – You can also confirm the languages your watch face will support by using the Monkey C: Edit Languages option.