hiit stopwatch

Creating Your First App With Fuse

Now that you’ve learned the basic concepts of Fuse, it’s time to put things into practice and build an app. In this tutorial, you’ll learn how to develop an app using the Fuse framework. Specifically, you’re going to learn the following:

  • How to code using UX Markup.
  • How to use the Observable, Timer, and Geolocation APIs.
  • How to preview an app using desktop preview and custom preview.

If you need a refresher on Fuse, check out my previous post in this series: Introducing Fuse for Cross-Platform App Development.


To start working with Fuse, go to the downloads page and sign up for an account. You can also log in to an existing account if you have one. 

Fuse is available for both Windows and macOS. Download and install the correct installer for your platform. On the downloads page, they also point out the Fuse plugins available for various text editors. Install the one for your text editor. The Fuse plugins include code completion, goto definition, and viewing of logs generated from the app, all of which makes developing apps more convenient.

We’ll also cover how to preview the app using custom preview. This requires Android Studio or Xcode to be installed on your computer.  

A basic understanding of web technologies such as HTML, CSS, and JavaScript is helpful but not required.

What You’ll Be Creating

You’ll be creating a stopwatch app which also measures the distance covered. The distance is measured using geolocation. The user can also create laps, and the individual distance and time for each lap will be displayed on the screen.

Here’s what the app will look like:

Final Output HIIT Stopwatch

You can view the complete source code in the tutorial GitHub repo.

Creating a New Fuse Project

Once you have installed Fuse Studio, you should now be able to create a new Fuse project. Just open Fuse Studio and click on the New Fuse Project button. Enter the name of the project, and click Create:

Create a new Fuse project

This will create a new folder in the selected directory. Open that folder and open the MainView.ux file. By default, it will only have the  markup. Update it to include a , and then save the file:

The preview should now be updated with the text you specified:

Hello world output

That’s the main development workflow in Fuse. Just save the changes to any of the files in the project directory, and they will automatically get reflected in the desktop preview. 

You can also see the logs in the bottom panel. You can trigger your own by using console.log(), like in the browser. The only difference is that you have to JSON.stringify() objects in order to see their value, since the console.log() implementation in Fuse can only output strings. 

UX Markup

Now we’re ready to build the app. Open the MainView.ux file and remove the element from earlier. That way, we can start with a blank slate:

Including Fonts

Just like in an HTML document, the standard is to include the assets—things like fonts, stylesheets, and scripts—before the actual markup of the page. So add the following inside the  element:

This imports the font specified in the File attribute and gives it the name Thin. Note that this doesn’t make it the default font for the whole page. If you want to use this font, you have to use its name (Thin) on the specific text you want to apply it to. 

You can download the font from the tutorial GitHub repo. After that, create an assets/fonts/robot folder inside the root project directory and put the .ttf file in it.

If you want to use another font, you can download it from dafont.com. That’s where I downloaded the font for this app.

Next, we want to use icons inside the app. Fuse doesn’t really have built-in elements and icon sets which allow you to do that. What it offers is a way to include existing icon fonts in your app. Since icon fonts are essentially fonts, we can use the same method for including fonts:

You can download the icon font from the GitHub repo or download it directly from fontawesome.com. Note that not all icons on fontawesome are free, so it’s best to check the actual icon page before using it. If you see a “pro” label next to the icon, then you can’t simply use it in your project without paying. 

Including JavaScript

Next, we need to include the JavaScript file for this page. We can do that using the  element:

Don’t forget to create the scripts/MainView.js file at the root of the project directory. 

Creating New Components

To maximize code reuse, Fuse allows us to create custom components from existing ones. In the code below, we’re using a to create a custom button. Think of it like a div which acts as a container for other elements. In this case, we’re using it as a reusable component for creating a button. 

Fuse comes with many elements. There are elements for laying out content such as the , elements for showing user controls, pages and navigation, scripting and data, and primitives for building the UI. Each one has its own set of properties, allowing you to modify the data, presentation, and behavior.

To create a reusable component, add a ux:Class property to a presentation element that you’d like to use as a base. In this case, we’re using a as the base. You can then add some default styling. This is similar to how styling is done in CSS. Margin adds space outside of the container. Here we’ve only specified a single value, so this margin is applied on all sides of the panel. Color adds a background color to the element:

Inside the , we want to show the button text. We want to make this into a reusable component, so we need a way to pass in properties for when we use this component later on. This allows us to achieve different results by only changing the properties. 

Inside the , use the data type of the value you want to pass in as the name of the element, and then add the name of the property using ux:Property. You can then show the value supplied to the property by using {ReadProperty PropertyName}, where PropertyName is the value you supplied to ux:Property. This will allow you to supply a Text property whenever you’re using the  component.

Next, we want to offer the user some sort of feedback while the button is being pressed. We can do that via triggers and animators. Triggers are basically the event listeners—in this case, . And animators are the animations or effects you want to perform while the trigger is active. The code below will make the button 10% bigger than its original size and change its color. Duration and DurationBack allow you to specify how long it takes for the animation to reach its peak and reach its end.

Next, we create the component. As the name suggests, this is a button which only shows an icon as its content. This works the same way as the previous component, though there are a few new things we’ve done here. 

First is the ux:Name property. This allows us to give a name to a specific element so we can refer to it later. In this case, we’re using it to change its Color property while the button is being pressed. 

We’ve also used a conditional element called . This allows us to disable the  trigger when the value for is_running is a falsy one. We’ll supply the value for this variable once we get to the JavaScript part. For now, know that this variable indicates whether the timer is currently running or not.

Main Content

We can now proceed with the main content. First, we wrap everything in a . As the name suggests, this allows us to “stack” its children either vertically or horizontally. By default, it uses vertical orientation so we don’t need to explicitly specify it: 

In the code above, we used four values for the Margin. Unlike CSS, the value distribution is left, top, right, bottom. If only two values are specified, it’s left-right, top-bottom. You can use the selection tool in Fuse Studio to visualize the margins applied.

Next, we add a background image for the page. This accepts the file path to the background image you want to use. A StretchMode of Fill makes the background stretch itself to fill the entire screen:

You can download the background image I’ve used from the tutorial GitHub repo. Or you can find similar patterns on the Toptal website. 

Next, show the name of the app. Below it is the time-elapsed text field. This text needs to be updated frequently, so we need to turn it into a variable which can be updated via JavaScript. To output some text initialized in this page’s JavaScript file, you need to wrap the variable name in curly braces. Later on, you’ll see how the value for this variable is supplied from the JavaScript file:

Next, we use the component that we created earlier—not unlike in a web environment where we use the ID of the font. In Fuse, you have to use the Unicode assigned to the icon font you want to use. You also need to use &#x as a prefix. When this button is pressed (called Clicked), the addLap() function declared in the JavaScript file is executed:

In Font Awesome, you can find the unicode of the icon font on its own page.

Right below the button for adding a new lap is some text which indicates that the button above is for adding new laps:

Next, show the button for starting and stopping the timer. This also executes a function which we will declare later:

Next, we need to output the laps added by the user. This includes the lap number, distance covered, and time spent. The element allows us to iterate through a collection of objects and display the individual properties for each object:

In the code above, we’re using the to wrap the contents for each item. This type of panel allows us to “dock” its children on different sides (top, left, right, and bottom) of the available space. By default, this positions its children directly on top of each other. To evenly space them out, you need to add the Alignment property. 

JavaScript Code

Now we’re ready to add the JavaScript code. In Fuse, JavaScript is mainly used for the business logic and working with the device’s native functionality. Effects, transitions, and animations for interacting with the UI are already handled by the UX Markup.

Start by importing all the APIs that we need. This includes Observable, which is mainly used for assigning variables in the UI. These variables can then be updated using JavaScript. Timer is the equivalent of the setTimeout and setInterval functions in the web version of JavaScript. GeoLocation allows us to get the user’s current location:

Next, we initialize all the observable values that we’ll be using. These are the variables that you have seen in the UX markup earlier. The values for these variables are updated throughout the lifetime of the app, so we make them an observable variable. This effectively allows us to update the contents of the UI whenever any of these values change:

After that, we can now set the initial values for the toggle button and timer text:

That’s how you change the value of an observable variable. Since these are not inside any function, this should update the UI immediately when the app is launched.

Set the initial values for the timer, lap time, and location for each lap:

The toggle() function is used for starting and stopping the timer. When the timer is currently stopped and the user taps on the toggle button, that’s the only time we reset the values for the timer and laps. This is because we want the user to see these values even after they stopped the timer. 

After that, get the user’s current location and push it on the locations array. This allows us to compare it to the next location later, once the user adds a lap. Then, create a timer which executes every 10 milliseconds. We increment both the overall time and the lap_time for every execution. Then update the UI with the formatted value using the formatTimer() function:

When the user stops the timer, we delete it using the delete() method in the timer. This requires the timer_id that was returned when the timer was created:

Next is the function for formatting the timer. This works by converting the milliseconds into seconds and into minutes. We already know that this function is executed every 10 milliseconds. And the time is incremented by 1 every time it executes. So to get the milliseconds, we simply multiply the time by 10. From there, we just calculate the seconds and minutes based on the equivalent value for each unit of measurement:

Every time the user taps on the refresh button, the addLap() function is executed. This adds a new entry on top of the laps observable: 

Here's the function for getting the distance covered in meters. This uses the Haversine formula:

Don't forget to export all the observable values:

Geolocation Package

To keep things lightweight, Fuse doesn't really include all the packages that it supports by default. For things like geolocation and local notifications, you need to tell Fuse to include them when building the app. Open StopWatch.unoproj at the root of your project directory and include Fuse.GeoLocation under the Packages array:

This should instruct Fuse to include the Geolocation package whenever building the app for custom preview or for generating an installer. 

Setting Up for Custom Preview 

Before you can run the app on your iOS device, you need to add a bundle identifier to the app first. Open the StopWatch.unoproj file and add the following under iOS. This will be the unique identification for the app when it's submitted to the app store:

Next, on Xcode, log in with your Apple developer account. If you don't already have one, you can go to the Apple developer website and create one. It's actually free to develop and test apps on your iOS device. However, there are some limitations if you're not part of the developer program.

Once your account is created, go to Xcode preferences and add your Apple account. Then click on Manage Certificates and add a new certificate for iOS development. This certificate is used to ensure that the app is from a known source.

Once that's done, you should now be able to run the app on your device. Click on Preview > Preview on iOS in Fuse Studio and wait for it to launch Xcode. Once Xcode is open, select your device and click the play button. This will build the app and install it on your device. If there's a build error, it's most likely that the preview bundle identifier is not unique:

change the bundle ID

Changing the Bundle Identifier to something unique should solve the issue. Once the error under the signing section disappears, click on the play button again to rebuild the app. This should install the app on your device. 

However, you won't be able to open the app until you approve it. You can do that on your iOS device by going to Settings General Device Management and selecting the email associated with your Apple Developer account. Approve it, and that should unlock the app.

For Android, you should be able to preview the app without any additional steps.


That's it! In this tutorial, you've learned the basics of creating an app using the Fuse framework. Specifically, you've created a stopwatch app. By creating this app, you've learned how to work with Fuse's UX Markup and a few of Fuse's JavaScript APIs. You also learned how to use Fuse Studio to preview the app on your computer and your phone while developing it.

Powered by WPeMatico

Leave a Comment

Scroll to Top