In September this year, I attended AthTech'21, a conference on sports data and technology. There, we discussed systems interoperability and user (fans) engagement through technology. During one of the sessions, I presented an idea to attract the spectators' interest in concrete athletics events like throws and jumps. I developed a simple but functional prototype on a quick app.

The result is a quick app with information about competitor’s performances in a competition, notifications. and sharing using third-party apps:

Long Jump quick app

This framework enables us to experiment with users interfaces, quick prototyping, and advanced capabilities to make the most of users' devices. Its modular approach allows us to reuse UI components and access dedicated APIs and services to facilitate the development of simple and light applications with excellent user experience. This article explains the key aspects of the quick app’s development, applying to a real example that you could reuse and try by yourself.

Pages, Components and Elements

Quick apps are composed of reusable components organized in pages and defined in documents identified by the extension .ux, encapsulating the quick app pages structure, logic, and rendering information.

We can reuse the components, scoping the functionality and user interfaces for a better organization and maintenance of the quick app. As shown in the following picture, we can define quick app components based on essential elements like in HTML (i.e., lists, images, divs, …) and other components in a hierarchical way.

Quick App Components

Build a Component

We can either define our local components or use external ones, like this open source library.

Quick app components are defined in UX documents structured in three sections:

  • Rendering template. Identified by the <template> tag, this section specifies the structure of the component, including rendering information (i.e., content and visual elements) and logic (i.e., conditionals, loops,..).
  • Stylesheet. Identified by the <style> tag, this optional section includes the local stylesheets of the current component.
  • Scripts. Identified by the <script> tag, this section defines the components' functions and business logic, including managing the lifecycle of the instances created in runtime (i.e., events when created, destroyed, etc.).

Templates support data interpolation to bind data variables and functions from the script to the view, enabling complex operations on the logic engine. The separation of the logic (JavaScript) and rendering engines brings us reactivity and high performance. We can also bind user interaction events produced in the view with handlers in the component’s logic.

We can synchronize data between the logic and the view using the {{mustache}} notation and binding variables.

The following example shows a component with an image and a text. The structure of the component is built with the basic elements, div, image, and text. The content is specified in the data object within the script. Any change on these variables will be rendered reactively.

<template>
  <div class="header">
      <div class="header_box">
        <div>
          <image src="{{ logoUrl }}"></image>
          <text>{{ titleContent.title }}</text>
        </div>
      </div>
  </div>
</template> 
<style>
  .header {
    flex-direction: column;
    justify-content: space-between;
    width: 100%;
    margin-bottom: 8px;
  }
  .header_box {
    height: 36px;
    width: 230px;
    margin-left: 12px;
  }
</style>
<script>
  module.exports = {
    props: ["titleContent"],
    data: {
      titleContent: {
        title: "Title of the quick app"
      },
      logoUrl: "https://example.org/images/logo.png",
    },
    onInit: function () {
        console.log('onInit triggered')
    },
  };
</script>

In the style section, we can apply styles to the components. We can use a profile of the standard CSS but also preprocessing with LESS and Saas.

Reuse Components

As shown in the picture above,we can create several sub-components as part of a component to simplify the app’s maintenance and for a cleaner code. For instance, we want our quick app’s pages to always have the same structure, so we create three sub-components: header, grid and footer. We define the components individually and load them through the import directive. Once they are loaded, we can directly use them as another essential element within the component.

For instance, we can import the component header.ux and use it within the main component, passing parameters from the parent as the header’s title.

<import name="header" src="./common/component/header/header.ux"></import>
<import name="footer" src="./common/component/footer/footer.ux"></import>
<import name="grid" src="./common/component/grid/grid.ux"></import>
<template>
  <div class="grid_box" >
    <header title-content="{{ titleContent }}"></header>
    <grid></grid>
    <footer></footer>
  </div>
</template> 
<script>
  module.exports = {
    data: {
      titleContent: "My app"
    }
  }
</script>

With this modular hierarchical approach, we can create structures as complex as we need. Now, we need to define the application’s routes (the pages or sections) and the components associated with each page. If we want to create two pages, home and detail, whose components are defined in components with the same name (home.ux and detail.ux), we need to specify this in the manifest.json document:

{
  // ...
  "router": {
    "entry": "home",            // The entry page is "home"
    "pages": {
      "home": {
        "component": "home",    // "home.ux" (no need to specify the extension)
        "path": "/"             // Component located at {src}/home.ux
      },
      "detail": {
        "component": "detail",  // "detail.ux" (no need to specify the extension)
        "path": "/detail"       // Component located at {src}/detail/detail.ux
      }      
    }
  },
  // ...
}

In the manifest, we can also configure the general look and feel of the application (i.e., orientation, colors, menus, …), other setup options, and basic metadata about the application. Read more about the quick app manifest.

Use APIs and Services

Apart from the rendering part based on components, we can use built-in APIs and services to deliver rich user experiences, from push notifications and user dialogs to advanced multimedia management and efficient control of the communications (e.g., fetch resources, upload/downloads,…).

In case we need to use one of these services, you usually need to specify it in two places:

Step 1: Add the service in the manifest.json, as an advanced feature:

{
  // ...
  "features": [
    {
      "name": "system.prompt"           // Service to show dialogs
    },
    { 
      "name": "system.notification"     // Service for push notifications
    },
    {
      "name": "system.share"            // For third-party data sharing
    }
  ],
  // ...
}

These declarations enable the system to pack only the libraries the app needs in compilation time.

Step 2: Import these services and use them in the scripts:

<template>
    <div>
        <div class="item" onclick="shareResult">
            <text class="item_attempt">Click me to share something</text>
        </div>
    </div>
</template>
<script>
    import share from '@system.share';
    module.exports = {
        shareResult() {
            share.share({
                type:"text/html",
                data:"Hey, I'm sharing data with others!!",
                success: function(data) {
                    console.log("Success sharing");
                },
                fail: function(data, code) {
                    console.log("Sharing failed, code=" + code);
                }
            });
        }
    };
</script>

Following this way, we can apply more advanced features, like running services in the background, checking and installing native applications in the device, accessing the calendar and contacts. See all services.

You can get the code from the Quick App Initiative’s repository and enhance the app with real athletes and data. If you are interested in learning more about the quick app framework, look at our section for developers, with a quick start guide and reference documents about the quick app platform. You are also invited to join us and contribute with more examples, guides, and opinions.