Autobiography of a high-fidelity prototype

Using Airtable and W3.js to create an efficient, repeatable web prototype for UMHealthResearch.org

Hi you’ll!

My name is Peak. I am a high fidelity prototype. People often tell me that I am beautiful, colorful, even shiny. At first, I liked it when people said that but now, I find myself getting angry. I want to tell them that I am so much more. What they see is literally just the surface. My creators, the designers working on UMHealthResearch.org, explained to me that this was because we had never exposed people to how I was created and what I had achieved. They asked me to tell you my story.


Prototypes and where they fit in the product life-cycle. A high-fidelity prototype is most useful when the product direction is relatively established.
Prototypes and where they fit in the product life-cycle. A high-fidelity prototype is most useful when the product direction is relatively established.

You don’t choose your family. They are God’s gift to you, as you are to them.

First, let me tell you about my family. I belong to a family of prototypes. They have all been in the service of UMHealthResearch.org. My father, the inVision prototype, explained to me our great lineage. He told me that my grandfather, the paper prototype, was really the one who started it all. While he was crude and rough, he had helped shape the basic ideas & flows within this latest incarnation of UMHealthResearch.org. My father had built on his success and helped define the macro-interactions. He told me that I would go further than any of them had ever gone, which eventually proved true. I built on my ancestors work and helped define the micro-interactions in the new version. I also helped with branding, stakeholder engagement, business analysis and testing.


Beauty is what lies within.

My father, as great as he was at exposing shortcomings with user flows, was not able to help build or test granular interactions — something that designers call microinteractions. Microinteractions are contained product moments that revolve around a single use case. Take for example, the task of assigning labels to potential participants. This is a singular task and results only in minor UI changes. These kinds of interactions exist everywhere. In fact, these interactions add up to play a major role in making a product usable and understandable. That is why I was born — not to be beautiful but to help the designers test these small but essential interactions.

The designers tell me that creating a good high fidelity prototype is an art. I was raised to be modular, easily updatable and to have real content. My inner workings are actually quite amazing. Let me tell you how I can about:

1. Repeatable UI components using W3.js

Creating repeatable UI components makes high fidelity prototyping more efficient.
Creating repeatable UI components makes high fidelity prototyping more efficient.

At first, they created static repeatable UI components. These components were then brought together using W3.js which is a JavaScript library that simplifies prototyping. I needed to evolve easily. The designers explained that if any part of me was difficult to change, it would inevitably not be changed, and I would not evolve. So they wanted to make sure things were easy to update.

One example of a repeatable component is my global navigation bar. This bar looks something like below, and shows up on a lot of my pages.

My global navigation bar.
My global navigation bar.

To create this bar, my designers first created a separate HTML file that only had the global navigation markup:

//Back to study list
<a href="study-list.html" class="logo-M" title="Back to Study List">
<span class="fa fa-chevron-circle-left fa-margin-right" aria-hidden="true"></span>
<span class="label" aria-hidden="true">Study List</span>
<span class="show-for-sr">Study List</span>
</a>

//Study Title
<h1>Energy Impact of Connected and Automated Vehicle Technology (Local Ann Arbor Drivers of Electric and Hybrid Vehicles)</h1>

//Log out and other navigation
<nav>
<a id="aLogout" href="" class="logout" title="Logout">
<span class="fa fa-sign-out fa-margin-right" aria-hidden="true"></span>
<span class="label" aria-hidden="true">Log out</span>
<span class="show-for-sr">Log out</span>
</a>
</nav>

global-nav.html

Then they included this bar on various pages using W3.js.

<section w3-include-html="./includes/global-nav.html" class="global-nav-st">
</section>

Include modules on pages using W3.js

This meant that if something needed to be changed with this component, it only needed to be changed in one place. The designers called this “Designing for change”.

2. Real content using Airtable

Adding live data to high fidelity prototypes makes testing real-life scenarios possible.
Adding live data to high fidelity prototypes makes testing real-life scenarios possible.

It was then time to add real data. They used Airtable to house the data. Being able to change the design and see how it looked with real content was very important for my designers and using Airtable made this easy and efficient. It also helped them test real life scenarios with users. They would add data to Airtable during a user test to mimic a new participant being added or a participant’s state being changed and see how our users reacted.

The Interested Participants interactions are a good example of this.

The Interested Participants interactions. All the participant data on this screen came from an Airtable base.
The Interested Participants interactions. All the participant data on this screen came from an Airtable base.

All the participant data in the app, on this and other screens, came from an Airtable base. This meant that I could grow up efficiently, because the data was separate from how it was presented. The Airtable base looked something like this:

An Airtable base. Storing data here allowed my designers to separate the content from design and move more efficiently.
An Airtable base. Storing data here allowed my designers to separate the content from design and move more efficiently.

Let me take you a little bit deeper. The Interested Participants page pictured above contains a list of participants. This list contains multiple participants snippets — little components that give overview information about a participant.

A participant snippet. A list of participants is made up of many such participant snippets.
A participant snippet. A list of participants is made up of many such participant snippets.

The markup for my participant snippet is stored in a separate file.

<article class="volunteer-snippet {{List}}">
<div class="body">
<div class="checkbox">
<label for="checkbox-{{ID}}">
<input type="checkbox" id="checkbox-{{ID}}" onchange="enableActionBar()" class="vol-checkbox" />
<span class="show-for-sr">Selet this volunteer</span>
</label>
</div>
<a href="profile-interested.html" class="main">
<section class="vol-info">
<header>
<h1>{{Name}}</h1>
</header>
<section class="summary">
{{Gender}}, {{Age}} years old <br/>
{{Location}}
</section>
</section>
<section class="aux-info">
<div class="list">
{{List}}
</div>
<div class="doi">{{DoI}}</div>
<div class="message-notification">
<span class="fa fa-envelope fa-margin-right"></span><span class="messages">{{Messages}}</span>
</div>
</section>
<section class="labels">
<span class="{{Labels}}">
{{Labels}}</span>
</section>
</a>
</div>
</article>

participant-snippet.html

Places where data needs to be inserted are represented by the {{}}. {{Name}}, {{Age}} and {{Gender}} are just a few examples. Note that these map to the columns in the Airtable base above.

Now, when my Interested Participant page loads, I work with the Airtable API to get the data from Airtable. Then I use w3.js easy, one-line data binding capability to display that data on the screen.

var Airtable = require('airtable');

// Get a base ID
var base = new Airtable({ apiKey: 'yourAPIKey' }).base('yourBaseID');

//Define volunteers object
var volunteers=[];
var arrLabels=[];
var varFilterByFormula="{List} = 'New'";

//Load and display volunteers
var loadVolunteers = function() {
base('Volunteer Table').select({
filterByFormula : varFilterByFormula,
sort: [
{field: 'Date of Interest', direction: 'desc'}
]


}).eachPage(function page(records, fetchNextPage) {
records.forEach(function(record) {
console.log('Retrieved ', record.get('Name'), record.get('Age')),
record.get('Location'),
record.get('Gender'),
record.get('Labels'),
record.get('List'),
record.get('Messages'),
record.get('Date of Interest'),
record.get('Conditions');

arrLabels.push(record.get('Labels'));
volunteers.push({ID:record.get('ID'),Name:record.get('Name'),Age:record.get('Age'),Location:record.get('Location'),Gender:record.get('Gender'),Labels:record.get('Labels'),List:record.get('List'),Messages:record.get('Messages'),DoI:newDate,Conditions:record.get('Conditions')});
});
fetchNextPage();
}, function done(error) {
console.log(error);

//Display data in volunteer snippet on UI using w3.js
window.w3.displayObject("volunteers", {volunteers:volunteers});
});
};

That’s it. Live data, here I come!

3. Interactivity

Adding interactivity to components with live data allows you to test & refine microinteractions.
Adding interactivity to components with live data allows you to test & refine microinteractions.

Now that I was pulling in live data, my designers moved on to adding interactivity to the most important tasks that users would perform. This is where essential micro-interactions were tested. My designers wanted to see how real data affected these interactions and if users found their designs understandable. Imagine for instance, that you want a user to filter your Interested Participant list by Gender to test your micro-interaction. When the Filter link on my Interested Participants screen is clicked, I call the following javascript function and display the filtered list:

function loadFilteredVolunteers(){
//Update List Title
if(document.getElementById("radioFilterMale").checked == true)
{
varFilterByFormula="{Gender} = 'Male'";
document.getElementById("spanVolunterListTitle").innerHTML = "Males found";
}
if(document.getElementById("radioFilterFemale").checked == true)
{
varFilterByFormula="{Gender} = 'Female'";
document.getElementById("spanVolunterListTitle").innerHTML = "Females found";
}

//Load filtered volunteers
$('#volunteers').empty();
volunteers = [];
loadVolunteers();

//Update Navigation Bar
$('.secondary-nav a').removeClass('active');
$('#aAll').addClass('active');
$('#asideFiltersContainer').popup('toggle');
}

An example interaction.

I have such small interactions throughout me. This helped my designers figure out little interaction details and provide specific instructions about them to the developers.


A superstar

At the peak of my career, I was a superstar. I was shown around to stakeholders, designers used me to experiment, users played with me, BA’s took pictures of me and used them in their documents, developers looked at me again and again, and QA used me as a reference to test the real product that was being built. I was the center of many a conversation.


What goes up, comes down

Slowly but surely, things began to change. I did not realize this but I was helping to build the end of me. The shiny new UMHealthResearch started getting all the attention. It looked just like me, but was far more sophisticated and complex. Now the designers did not use me as much, I rarely saw any users and the BA’s, well they never came back.


Success is inspiring change

Telling you my story has been therapeutic. It has allowed me to reflect on my life. It has made me aware of the fact that my father, the inVision prototype, and his father, the paper prototype, went through similar cycles. It has made me realize that it is the destiny of us prototypes to inspire change. How well we do that defines how successful we are, and I for one have had a Peak career. Cheers!