Are you handy with HTML but haven’t mastered JavaScript? Do you lack the skills to program database back ends for web applications? In this tutorial, learn how Mavo, a open source web application framework, enables you to create web applications without writing programming code or configuring a server back end.

Mavo opens up data-driven web application development to a broader base of creators, and, specifically, to HTML users. The framework extends HTML to support data definition and manipulation through intuitive constructs. An easy-to-use user interface enables editing for all sorts of data types, including numbers, dates, images, simple and rich text, lists, and much more. Its expression language, MavoScript, was carefully created through research and user testing to ensure that people who are not familiar with JavaScript can enable the data manipulation common in web applications.

Ultimately, most Mavo apps are just HTML files, which you can base on any preferred design templates, as long as they have two required lines of Mavo declarations and a few stylesheets. This makes it very easy to deploy Mavo apps and change them over time. Just copy a few files to your web host and you’re ready to go.

Mavo can’t replace all application development. On the contrary, since the project is still young, it’s limited in the scope of what it can handle. Nevertheless, it’s a pleasant, useful way to do rapid prototyping or build simple applications. Mavo is easy to learn and experiment with, so the best way to decide whether it will suit your needs is to look at some examples.

Mavo overview

A quick Mavo overview

Write your first Mavo app

To familiarize yourself with Mavo, let’s walk through how to create a single app on a simple page. First you need to make a few decisions about how to set up the development of your app.

  • Will you download the Mavo files to your site or include them directly from the Mavo site?
  • What back-end system do you want to use to store any data changes in the app?
  • What identifier do you choose for your app?

Determine where to include the Mavo files

Each Mavo app page requires that you use two Mavo-specific files, a CSS file and a JavaScript file. You can use the latest version directly from the Mavo project, as illustrated in the following snippet:

<link rel="stylesheet" href="https://get.mavo.io/mavo.css"/>
          <script src="https://get.mavo.io/mavo.js"></script>

Or you can include these files from your own site:

<link rel="stylesheet" href="assets/style/mavo.css"/>
          <script src="assets/script/mavo.js"></script>

Loading the files directly from Mavo ensures your apps always use the latest version, including any security hotfixes. The downside is that, if the Mavo project introduces any incompatibilities or bugs, your apps could break without warning. You may need to load directly from Mavo if you are in an environment that constrains your ability to host the two files.

If you’re not sure which option to pick, go ahead and link to the Mavo files directly at mavo.io.

Decide about data storage

You need to have a plan for where to store your data, whether locally on a browser, in a data or code repository like Dropbox or GitHub, or in a database.

Your best option is probably to use external storage, such as GitHub or Dropbox storage. When you create your account, take note of any storage restrictions for your account type. Even though GitHub is normally a tool for the more technically minded, Mavo abstracts away the details to make it easy to use for storage.

If you store your data locally on a browser, be aware that other users won’t be able to see your changes and that all changes will be lost when you close your browser. Typically, storing data in your browser’s local storage is only suitable for sandbox applications where other users won’t need to see your changes and when it won’t matter if your data is reset when the session ends.

Even though browser storage is limited, I’m going to use it in this article to show you the basics of Mavo. In the next article, I will talk about GitHub storage.

Advanced developers with JavaScript skills can also create their own storage plugins, say to a database.

Create an application identifier

You need to assign your app an identifier, which will be used for several details of its automatic workings. If you don’t assign your own identifier, Mavo will give you a default one which can complicate the process later on.

To create an identifier, start with a short, memorable name for the app and then remove any characters other than letters and numbers, replace spaces with underscores, and finally make sure the result starts with a letter or underscore. The identifier in the sample application below is “poetryclub”.

Sample application

In this article, I’ll introduce you to the basic features of Mavo by showing you how to build a Poetry Book Club notice page.

Mavo application element

The heart of the Poetry Book Club application code is a main element within the HTML body. The main element is a container for the prominent body of content. In this case, it is also the container structure of the Mavo app. This is indicated by its mv-app attribute, whose value is the chosen application identifier. The full opening tag looks like this:

<main mv-app="poetryclub" mv-storage="local">

This is called the Mavo app element or declaration, and it can be placed on any HTML block elements, not just main, but even article or div. Mavo introduces specialized attributes with the mv- prefix. The mv-storage attribute indicates where to store the data that’s processed by the app. If its value is none or the attribute is omitted altogether, nothing will be stored. If, as above, its value is local, the data is stored in browser-local storage.

Mavo properties

Within a Mavo application element, any element with a property attribute becomes a data item which can be manipulated and saved. Consider the following snippet:

<p>
  <label>Title: </label>
  <span property="title">Ndewo, Colorado</span>
</p>
<img property="cover" src="http://gonzaga.ogbuji.net/~uche/lit/2013/ndewo-cover-small.jpg"
alt="cover" />
<p>
  <label>Meeting date: </label>
  <time property="meeting" datetime="2017-10-09">9 Oct 2017</time>
</p>

Within the top p element, a span declares and governs a Mavo data property named title. With Mavo, any HTML 5 element can govern a property, and Mavo defines user editing behavior for each type of element according to what makes sense for the semantics of that element type. For example, in this case, the editing mode is a single-line text input. If a property were instead governed by a block element such as p, the editing mode would be a multiple-line text input.

cover and meeting properties are also in the above snippet. The img element governs cover, and the editing mode is an input for a replacement image URL. A time element governs meeting, and the editing mode is a calendar widget.

Full Poetry Book Club example

bookclub1.html, shown in Listing 1, is the entire HTML file from which the above snippets are taken.

Simple Poetry Book Club notice page
<!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="utf-8">
    <title>The poetry book club</title>

    <link rel="stylesheet" href="https://get.mavo.io/mavo.css"/>
    <script src="https://get.mavo.io/mavo.js"></script>
  </head>
  <body>
    <main mv-app="poetryclub" mv-storage="local">
      <h1>The poetry book club</h1>

      <p>
        <label>Title: </label>
        <span property="title">Ndewo, Colorado</span>
      </p>
      <img property="cover" src="http://gonzaga.ogbuji.net/~uche/lit/2013/ndewo-cover-small.jpg" alt="cover" />
      <p>
        <label>Meeting date: </label>
        <time property="meeting" datetime="2017-10-09">9 Oct 2017</time>
      </p>

    </main>
  </body>
  </html>

Mavo in action

When I load the bookclub1.html file into the browser it shows a simple Poetry Book Club notice page, as in Figure 1:

Simple Poetry Book Club notice page

Simple poetry club notice page in browser

Notice the Mavo action bar at the top of the page. When I click the “Edit” button, the editing features appear.

Figure 2 shows the page after the I click “Edit” and start changing the title field. Notice the button has changed to say “Editing”. If I click this button again, the page goes back to its normal viewing state, without the special editing behaviors.

Poetry Book Club notice page in user edit mode

Simple poetry club notice page in browser, in user edit mode

When I click the image, a field pops up where I can replace the URL and upload a new image. Incidentally, Mavo requires that you provide an alt attribute for each image declared with a property. This is, of course, what you should be doing anyway.

Editing an image in Mavo

Simple poetry club notice page in browser, editing image

When I click the meeting date, it brings up a calendar widget, as Figure 4 shows:

Editing a date in Mavo

Simple poetry club notice page in browser, editing date

The “Clear” button allows you to undo all changes from the editing session.

If you pay close attention, you’ll see that Mavo uses the property names in various ways in the editing tools. For example, if you click to edit the image, the label of the field where you can enter the new URL is “Cover:”, which is taken from the property name.

Mavo expressions

Now that I’ve shown you how to declare and manipulate data items, let’s talk about automation. Most apps have automated manipulation built into the code. You can use Mavo’s expression language, MavoScript, to enable this automation.

In this example, I want to add a link to the Poetry Book Club Page that emails the organizers and includes a subject line with the title of the current book. To enable this automation, I add the following snippet in the main element of the Mavo application.

<a href="mailto:poclub@example.com?subject=[title]">Contact us about this meeting</a>

The [title] part is Mavo’s default expression syntax which you can replace in the HTML with the value of the title data item. Mavo’s expressions are flexible. So, for instance, if you want your email’s subject to always be uppercase, you could use the following code:

<a href="mailto:poclub@example.com?subject=[uppercase(title)]">Contact us about this meeting</a>

Here, uppercase(title) is a Mavo expression function that operates on the value of title and transforms it to all caps. In this example, the title “Ndewo, Colorado” was transformed to “NDEWO, COLORADO”. There are many Mavo expression functions, including ones to manipulate text strings, some to manipulate lists, some to manipulate dates and times, and some used for mathematical operations. The Mavo documentation page on MavoScript has a full list of these. You can also express most arithmetical operations using the customary symbols, as you’ll see below. You would normally need to write JavaScript that manipulates the HTML document object model (DOM) to enable such a feature, so immediately Mavo is making life a little bit easier for the developer.

Placing the Mavo app

The Mavo app does not need to be declared on the outermost element. Listing 2 is bookclub1.5.html, a variation of Simple Poetry Book Club notice page. Here, the Mavo app declaration is made on a div element which comes after the main heading and some additional descriptive text.

Poetry Book Club notice page in browser, with alternate Mavo app placement
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>The poetry book club</title>

  <link rel="stylesheet" href="https://get.mavo.io/mavo.css"/>
  <script src="https://get.mavo.io/mavo.js"></script>
</head>
<body>
  <main>
    <h1>The poetry book club</h1>

    <p>Where we take our time with each tasty rhyme</p>

    <div mv-app="poetryclub" mv-storage="local">
      <p>
        <label>Title: </label>
        <span property="title">Ndewo, Colorado</span>
      </p>
      <img property="cover" src="http://gonzaga.ogbuji.net/~uche/lit/2013/ndewo-cover-small.jpg" alt="cover" />
      <p>
        <label>Meeting date: </label>
        <time property="meeting" datetime="2017-10-09">9 Oct 2017</time>
      </p>
    </div>

  </main>
</body>
</html>

Figure 5 shows bookclub1.5.html in the browser as first loaded. Notice the positioning of the Mavo app bar, relative to the element on which the app was declared.

Alternate Mavo application placement

Poetry club notice page in browser, with alternate Mavo app placement

Number and date expressions, with style

Let’s revisit Mavo image properties so you can see how you can use Mavo expressions to do interesting things with images. You can upload any image to the Poetry Book Club page. To add customized image sizes, I replaced the img element with the following snippet:

<img property="cover" style="height: [height * 2 + 200]px;"
 src="http://gonzaga.ogbuji.net/~uche/lit/2013/ndewo-cover-small.jpg" alt="cover" />

 <div>
   <input type="range" property="height" />
 </div>

I introduced the height property here, which is declared as an HTML slider input. Mavo interprets this as a control that sets the value from 0 to 100 as the user slides it. The img now has a new style attribute which sets the height of the image through CSS declaration according to a Mavo expression. This expression is a simple mathematical formula based on the height: [height * 2 + 200]. In this case, the image ranges from 200 with the input slider on its lowest setting, to 400 with the input slider on its highest setting.

Conditional expressions in Mavo

When the meeting is less than a week away, I want to highlight the meeting date in yellow to draw attention to it. To do this, I replace the current date section with the following snippet.

<p style="background-color: [if(days(meeting - $today) < 7, yellow, white)];">
  <label>Meeting date: </label>
  <time property="meeting" datetime="2017-10-09">9 Oct 2017</time>
</p>

The if() function takes two or three arguments. The first is a condition expression.

  • If its value is true or non-zero, the second argument is set as the resulting value.
  • If the condition is false or zero and there is a third argument, this third one is used as the resulting value.

In this case, the condition is if(days(meeting - $today) < 7. The meeting property is the editable date of the meeting, as you’ve already seen. $today is one of several properties automatically provided by Mavo, and is always set to the present date as determined by the web browser.

The subtraction of the two date values results in a differential number of seconds, and the days() function takes this number of seconds and computes the equivalent number of days. If the outcome of this is less than seven days (notice the standard HTML need to escape < as <) the condition is true, and the second argument, yellow is set as the result. Otherwise, the result is white. In this case, it’s a good idea to style the page background to be white, but that’s a fine detail.

The color arguments look like they could be property names. When Mavo finds something that looks like a property name, it replaces it with the property’s value, if there is such a property. Otherwise, it treats the text literally. If you want to be sure something that could look like a property is treated as literal text, you can quote it. The following conditional behaves in the same way: [if(days(meeting - $today) < 7, 'yellow', 'white')].

The full Poetry Book Club example

Listing 3 is bookclub2.html, the entire HTML file from which the above snippets are taken. It is based on Simple Poetry Book Club notice page, but with added use of MavoScript.

Poetry Book Club notice page, using Mavo expressions
  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="utf-8">
    <title>The poetry book club</title>

    <link rel="stylesheet" href="https://get.mavo.io/mavo.css"/>
    <script src="https://get.mavo.io/mavo.js"></script>
  </head>
  <body>
    <main mv-app="poetryclub" mv-storage="local">
      <h1>The poetry book club</h1>

      <p>
        <label>Title: </label>
        <span property="title">Ndewo, Colorado</span>
      </p>
      <img property="cover" style="height: [height * 2 + 200]px;"
       src="http://gonzaga.ogbuji.net/~uche/lit/2013/ndewo-cover-small.jpg" alt="cover" />

       <div>
         <input type="range" property="height" />
       </div>

      <p style="background-color: [if(days(meeting - $today) < 7, yellow, white)];">
        <label>Meeting date: </label>
        <time property="meeting" datetime="2017-10-09">9 Oct 2017</time>
      </p>

      <a href="mailto:poclub@example.com?subject=[uppercase(title)]">Contact us about this meeting</a>

    </main>
  </body>
  </html>

Mavo in action with dynamic changes

Web browsers compute and apply style changes dynamically. MavoScript lets you input some neat, dynamic responses, which normally require JavaScript. Figure 6 shows what the page looks like when I adjust the meeting date to within seven days of the present date and pull the image size slider to the maximum.

Poetry Club notice using Mavo expressions

Poetry club notice using Mavo expressions, in edit mode

Limitations of Mavo

While Mavo won’t alleviate the need for programmers, it’s a great tool to use for creating compact applications that work entirely within one web page. MavoScript, its expression language, is very well thought out, but can’t extend all the capabilities that JavaScript offers, including creating sophisticated applications that require carefully coordinated user sessions maintained across sequences of web pages. Mavo’s approach to simplifying server-side storage is clever, but by no means suitable for the majority of apps.

Realities of storage

My examples in this article used only browser-local storage, which isn’t very useful in practice. In Part 2 of this series, I’ll show you how to use the GitHub storage back end with Mavo. Mavo is best suited to this “chunky storage,” where users make sets of content updates and then submit all these for approval.

There are many other approaches to storage that are used in the web application world. For example, an online transactional database, like one used in e-commerce, can handle numerous users making simultaneous, fine-grained changes. In theory, you could write a database backend for Mavo to support such a model. But, in practice, the sophistication of code and the need to adapt the behavior of Mavo’s built-in model for most use-cases makes this type of storage too complicated to be used with Mavo.

Go forth and Mavo

It is important to understand the limitations of Mavo, but don’t let these limitations discourage you from using this very promising project. The team who created Mavo used detailed research related to simplifying programming concepts for non-programming web professionals to create a pleasant user experience.

Mavo is easily extendable and interacts cleanly with the full power of JavaScript. These features make it quite useful for rapid prototyping by web designers, and speed deployment of full-blown applications for which the chunky storage model is well suited.