Mathew Sanders /

Designing in the browser: data‑driven prototypes & living style guides

TL;DR

This is a tutorial that walks you through the steps needed to move from a static composition to a data-driven prototype, and a living style guide.

After a ramble about the benefits of designing in the browser, and how to choose what tools to use, I walk through a practical step-by-step example of an simple web app to find nearby cafes built using the Vue.js framework, and using a fieldbook.com spreadsheet as the source of data.

This is a looooooong post, if you only have a couple minutes I’d recommending a quick look at the example living style guide and sample scenario showing cafes in New York to get an idea of the outcome before coming back for the entire tutorial.

The living style guide lists each modular component that your app uses, and provides an ad-hoc way to explore how the components respond to different sets of data, and provides an entry point into your prototype to demonstrate different scenarios.

A scenario shows how your product concept performs in different states (for example, you could have scenarios to demonstrate different stages of customer onboarding from visitor to new member, to established member, or to show different locales).

Designing in the browser. What if I’m not convinced?

Design should be an iterative process where ideas are explored, evaluated, and refined.

For each of these different phases we have a bunch of tools that we use. A typical design team might use tools like paper sketching to explore, a diagramming tool like Omnigraffle to capture a flow, a graphics tool like Sketch or Photoshop for high-fidelity mocks, and perhaps a tool like Framer or Marvel to explore illustrations, or get feedback on a user flow.

But unless it’s for the purpose of an animation, it’s rare for a designer to write code in their day-jobs. And despite the popularity of the agile manifesto, collaboration between designer and developer is often reduced to consultation.

In my experience, when a designer presents work to a stakeholder its typically in the form of high-fidelity illustration. There’s an expectation that precision equates to perfection, and presenting something like a rough paper sketch would, in most cases, be considered careless.

Despite the fidelity of a screen compositions, these outputs are not the final stage in refining an idea, but actually just a latter step in the process of exploration and should be treated with similar regard as a paper sketch.

No matter how experienced you, your team, or your stakeholders are, I don’t believe that it’s possible to look at illustrations of an interface, suspend disbelief, imagine someone using the interface, and give useful feedback.

Collecting feedback on a concept by looking at it one screen at a time separates the product from the natural cadence that it would be used. Screens intended to be shown for a passing moment might be flagged as too boring, or taken out of context of an overall flow.

Feedback on illustrations make it extremely difficult to understand rich experiences, especially when the interface is intended to be used on a hand-held device.

Feedback on illustrations prompt refinement on aesthetic issues rather than potentially more impactful issues of usability.

The most significant issue with using illustrations for collecting feedback is that it creates a separation between content and design, with content generally becoming a second-hand citizen in the process.

Good designers will take into account edge-cases for content (for example unusually long names, or when content is omitted) but in most cases designs are evaluated with a snapshot of content.

In the world of research there’s a truism that the worst number of people to test with is one. In the same spirit, it’s incredibly dangerous to design a solution around a snapshot of content, especially if it’s made up.

Tools like Sketch are still essential for the design process. They’re the fastest way to take a general layout and quickly explore broad variations1.

Designing in the browser does’t mean abandoning your current design tools, and not making high-fidelity comps. It means a perspective shift from final deliverable to another useful tool.

That was the stick. Now for the carrot.

What benefits should I get by adding this to my workflow?

Designing in the browser means finding a design process that involves your concepts being evaluated in the browser.

Understanding (and using) the medium that you’re designing for will make a lot more sense when you actually try it for yourself.

If you’re still skeptical, consider creative geniuses of artists like Michelangelo and Picasso. Their workflow involved countless sketches of varying fidelity exploring composition and detail before starting a painting, but even with all that preparation, once painting had started it was still common to paint over large areas and make dramatic changes on the final canvas.

Some direct, and incidental benefits of designing in the browser include:

  • Content (or data) becomes first-class citizens. You’ll be able to easily explore and evaluate a range of scenarios.
  • You’ll actually be able to use your designs rather than just look at them. You’ll react and respond to your designs in a completely different way.
  • You’re encouraged to think about flows, edge cases and dead ends will become obvious.
  • Prioritization shifts from being an abstract to-do list, to having concrete consequences.
  • You’re encouraged to think about design from a modular approach, leading to re-use of components and consistency in the user experience (also, developers will love you).
  • You’ll get a better understanding and consideration for technical constraints (developers, feel free to buy me coffee).
  • You’ll immediately see how your designs adapt to different different browsers, different platforms, and sizes.
  • You’ll learn a lot in the process, and gain a common language that will help you better collaborate with your developers.
  • The last 10% (transitions, animations) will hopefully get deserved attention, rather than being left as an afterthought.

That’s a pretty impressive list of outcomes, and I can’t guarantee that designing in the browser will help everyone the same way.

Also, designing in the browser isn’t the only option that will lead to those benefits, depending on your team, your workflow, your product, and your company, you might already have alternative practices2 in place that are leading to these same outcomes. YMMV.

What options do I have, and how do I choose?

Specialized design & prototyping tools

There are dedicated prototyping tools like Axure that act as a proxy for writing code in favor of a GUI which then generates HTML on your behalf.

These tools terrify me because on the surface the drag-and-drop nature of the interface make them appear simple3, but that initial simplicity often hides an immense amount of complexity that people dedicate months (or years) mastering a specific tool when they could have been investing that time learning more general purpose programming tools.

Hand-crafted HTML

Another approach could just be hand-crafting HTML. This approach is okay-ish for the simplest of projects like a static marketing website, but for most situations suffers many of the same obstacles of high-fidelity comps in that it’s very difficult to explore different sets of data.

Development frameworks

The final option is to borrow a tool from our developer friends and use a MVC framework.

A framework gives us some structure to work around, and while every framework has an initial learning curve, in the long term will make our lives a lot easier.

The biggest problem that we face is deciding which language to use, and which framework to pick, todomvc.com is a site that assembles sample apps from web MV* frameworks and currently lists over 50 options.

When choosing a framework to use I look for the following:

  • Low learning curve: How fast can people with only basic experience with HTML get started?
  • Great documentation, examples & community: Is there clear documentation and examples available how to use the framework, and an active community available to help with issues?

Because our aim is to create experiences that are prototypes or proof-of-concepts, rather than release production ready code, then the following are mostly irrelevant:

  • Security: Don’t worry about creating code that keeps information private. Your prototypes should use real (or realistic), but anonymized content, and only be accessed in controlled environment.
  • Scalability: Don’t worry about creating code that needs to be maintained, or expected to remain functional in the long term.
  • Stability: Don’t worry about creating code that works 100% of the time. Again it will be used in controlled situations so it’s okay for there to be occasionally bugs.

The final consideration should be to consider the framework your development team is already using (or planning to use).

If you make a short-list of frameworks you’re interested in using, and one of those happens to be what is already being used in your company, then it’s a pretty strong argument to use that common framework, not because there is potential to re-use code, but because you’ll have access to a team that can help you learn that framework.

But if the framework your development team uses doesn’t meet your shortlist for a low learning curve, documentation, examples and community then it might be better to use a separate framework that better suits the criteria for your design team rather than to use a common framework.

There’s a lot of factors to consider in that decision. If that’s all too much then just go with my recommendations which are to use a combination of Vue (a javascript framework) and Fieldbook (which we’ll use as our place to store data).

The rest of this post continues by showing examples using Vue and Fieldbook. You can follow along to get a general idea, but you’ll need to adapt a lot if you choose to use a different framework.

Vue by example

This next section walks though the steps of taking an early concept and, the steps needed to get it transferred into the browser, and running off live data.

I’ve broken this process down into smaller steps so you can get a better idea of what’s happening, and learn more about Vue, in practice many of these steps would be skipped over.

This section assumes that you’ve already installed Vue.

Our concept: Cafe Finder

Let’s use the example of making a web app that helps people find independently operated cafes in a city.

Imagine that you’ve explored a range of directions, and settled on a layout that shows cafes as a grid of cards, where each card shows some details about the cafe. We’ve also decided that we’ll have two ways to sort the cards. By default in alphabetical order by name, and another based on how close they are to your current location.

Activity 1: Semantic markup

A good first step is to start by creating a sensible semantic markup in HTML. By not worrying about what the page looks like, but instead how it’s structured is a good way to avoid adding markup that isn’t needed.

For now I’m adding the ‘map’ only as a placeholder. It won’t actually show anything, but I’ll add it as an element so at least we can plan around the space that it will use.

Obviously, with no styles applied, this doesn’t look so great.

Activity 2: Add basic styles

Copy and paste the code for the cafe card a few times so that we have a few elements on the page to work with as we apply styles.

With some basic CSS in place, our page is starting to look a little more respectable.

And because we’re in the browser, we can immediately start to get a feel for how the screens will adapt to different viewports.

I might get some criticism for starting from the approach of a desktop, but personally I think the choice of mobile/desktop-first is irrelevant as long as you’re taking a responsive-first approach.

Activity 3: Extract repeating elements

So the annoying thing with our page right now is that we only have 3 cafe cards. We can copy-and-paste more into the HTML, but that also becomes annoying when you want to make a change across all of the elements.

For example, I’ve just realized that as well as the location, I also want to show the hours that the cafe is open.

What would be great would be if we could take this code:

And get the same result just by using a single <cafe-card></cafe-card> tag.

If we could do that, then our HTML would suddenly become a lot more easier to read:

Guess what? That’s exactly what Vue allows!

We can do this by creating a new file CafeCard.vue.

Notice that our HTML is wrapped in a <template> tag, and we’ve also copied over the relevant CSS for the cafe card and wrapped that CSS with a <style> tag.

You might have noticed the scoped attribute in the <style> tag. This is optional, and means that any CSS that we set here will only apply to the HTML in our template. So although we have a CSS rule for H1, because this CSS is scoped these styles won’t be applied to any H1 tags in other parts of the page.

What I love about this approach is that everything that you need for this component - the HTML structure, and the CSS is all in a single file, meaning you don’t have to jump around to figure out where a specific style is. As projects become more complex, this approach helps keep them manageable.

A couple steps before this actually works, we need to tell Vue about this new component we’ve created. This is done in a file called main.js.

And also add a script tag in index.html so that it everything can connect up.

Activity 4: Pass in the cafe’s name

That’s great, but each card still has the same repeated details.

Let’s make a change by passing in a name for each cafe.

Now back in CafeCard.vue we’ll need to make some changes, first to let Vue know that we’re passing in a property called name to the component, and also in our template so that it actually uses that name.

We’ll do this by adding a <script> tag to our .vue file, which for now just defines props as an array that contains all the properties we want to pass into the component. For now we’re just passing in name so the array only has one item.

Now our screen is starting to have some dynamic data, with the titles of each cafe being used in the card:

Activity 5: Use a loop to create the cards

Now we have 5 cafe cards, but we don’t want this to be hard-coded into our page. We want a solution that works with minimal fuss if we have 1 cafe, or 100 (or none).

Vue includes a directive for looping over an array of items that allows us to go from this:

to this:

This is assuming that cafeNames is an array that contains the names of all the cafes e.g. ["Daily Press", "Cafe Grumpy", "Stumptown", "Third Rail", "Gimmie! Coffee"].

Where do we create this array so that Vue can use it? We can pass it into Vue in our main.js file like so:

Activity 6: Pass in more data to each card

Now that we’re set up to pass information into our cafe-card component from a data source (currently just a simple array) lets’s use this to pass in all the details for each cafe.

The details for Cafe Grumpy can be captured in a Javascript object where details are recorded as key/value pairs.

Instead of an array of Strings, let’s create an array of these objects:

In our index.html we’re no longer passing in a name, but actually data about the entire cafe, so lets make some changes to reflect that:

Finally, in our CafeCard.vue let’s make use of this new data:

Now our template code doesn’t include anything hand coded, and everything is being rendered from our data source.

Activity 7: Show the cafe’s location on a map

An interesting thing about this approach of making our own components, is that they can be nested within each other just like any other regular HTML tag.

Just like we made a component by creating a CafeCard.vue file, I’m going to follow a similar process and create a GoogleMap.vue which contains all the logic to render a map showing a specific location, and then use this new component in the cafe-card component.

I won’t list out all the steps, but you can review changes that we made in main.js, CafeCard.vue, and the newly created GoogleMap.vue files.

Here’s our page with a map shown on each cafe card.

Activity 8: Refactor to create a Cafe Grid component

Right now we have two components, one for the map, and another for the cafe card.

A component can represent anything from as small as a button, to something of slightly more complexity like a card that bundles some related information, or a component could represent an entire screen!

By thing as components as modular elements of the screen, we can start to combine them to create more complex layouts, but also as a way to organize our project into sensible bits that make it easier to manage over the long term.

Let’s take all the code that’s currently used to manage this grid of cafes and put it into a component.

We won’t get any immediate payoff for this, but it will be more obvious why this is useful in the following steps.

We’ve moved all that data source stuff into our grid component so main.js gets a little more readable

And our index.html file is now crazy lightweight.

It’s interesting to reflect that functionally nothing has changed, but by adding a new component we’ve for the grid view we’ve moved a bunch of complexity into it, but that sort of makes sense since now pretty much everything important about that grid is in a single place rather than being split between index.html and main.js

Activity 9: Change the order that cards are sorted

Something great about rendering components from a data source is that you have the ability to manipulate that data source - you can add, remove, or alter items in your source, or you can change the order that items are presented which will all affect how our page lays out.

Vue includes options for sorting, limiting, and filtering arrays. Here’s a quick change that simply orders our cafes alphabetically.

What would be really cool tho, would be to allow us to change the order that cafes are presented by clicking on our options in the navigation section of the page. So let’s do that!

In the CafeGridView.vue we’ll add to our sort option links code that calls a method setSortOrder. We also need to create this method by adding it to our <script> section. This is a really simple method that just sets our sort order property to whatever get’s passed in as a parameter in the method.

When we loop over our cafes, instead of sorting by a value that’s hard-coded, it sorts based on whatever value sortOrder currently is.

We also need to make an update to our data source to add in some options for how far away that cafe is.

We’ll just fake it for now and enter in some pretend values, but obviously in a functional app these distance values would be calculated based on your actual current location.

Activity 10: Load data from an external source

Something that’s really useful is being able to explore changes to our data source without having to go in and edit our code.

For this example I’m going to show how to connect the data to fieldbook.com, which is similar to a Google Spreadsheet, except that it has convenient ways for us to grab that data in a format that’s easy for us to use in Vue.

To start, we’re going to change the <script> section of CafeGridView.vue to the following:

Our data block is suddenly a lot simpler because we just set cafes to the value of an empty array.

We’ve added a ready block, which like the name suggests is code that is executed when the component is ready to be displayed. This ready block includes some code that requests our cafe data from fieldbook.com, and then when it’s done, it updates our cafes array with that data.

We also need to make some updates to main.js

A lot of variables here are based on the fieldbook that I have made at fieldbook.com/books/56c3c166589a1f0300c53acd feel free to use this yourself, but if you create your own fieldbook book you’ll need to update the variables to match your details.

Now with our dependencies up to date, and our data being sourced from fieldbook.com it’s easy to make updates to the data without updating the project code.

Activity 11: Allow for multiple pages

At the moment our app only has a single page, the grid of cafes. Sometimes a project may only require a single page, but even on these projects I like to include a live style guide that acts as a place to store documentation for custom components that have been created.

So this next step will show how to add code that manages what to display based on the current URL.

We’ll set it up so that navigating to /#!/cafes/new-york shows our current grid view of cafes, and navigating to /#!/styleguide shows documentation about our project styles and custom components.

First we’ll create a new component StyleguideView.vue that will act as documentation for our components.

Next we need to add code that manages which component to show based on what the URL is. This is common task in web apps, and code that does this is called a router.

Router functionality isn’t a core component to Vue, but like vue-resource we can list it as a dependency for our project, and have it installed as an add on.

The most significant changes happen in our main.js file, here’s an extract of the most interesting changes:

index.html also gets changed where we use the special <router-view> component that comes as part of using vue-router.

Changes in this step we made to main.js, Styleguide.vue, index.html, package.json. Because we added a new dependency, you’ll need to run npm update to download and install the vue-router package.

Activity 12: Make the style guide dynamic

A benefit of having a live style guide in HTML, rather than a static style guide as a PDF, and components that are data-driven is that we can make the style guide dynamic and use it to explore how our components adapt to ad-hoc sets of data.

Basically, the approach I use is to add a <textarea> for each component that allows you to update the data that’s being used to render that component.

This creates something called two-way binding between our cafe data object, and the textarea so that any changes made in the textarea update the component in real time making it easy to explore how our component adapts to variations of data that’s used.

Activity 13: Deploy the prototype

So far our prototype has only been available when run locally from our computer. For an internal team sometimes that’s all that you need, but when you want to get feedback from people outside of your team you’ll want to have your prototype deployed to the internet.

A plus for using a framework like Vue, and Fieldbook for the datasource means that hosting the prototype is extremely simple because we don’t have any potentially complicated configuration of a server to manage, and we only need a static web host (e.g. a server that only hosts static files html, css, javascript, and image assets) which there are many low-cost and free options.

Again cli-vue helps us prepare for deployment. Like we use the command npm run dev to run a local server for development, we instead use the command npm run build which takes all our code,bundles it together, and minifies it so that it’s the fastest download possible.

Then all you need to do is upload index.html, dist/build.js and any css or image files needed (for us this includes default.css) to a web host.

I’ve uploaded these files for the cafe-finder prototype to getforge.com which will host your first site for free, and deployment is as simple as dragging a zip of your files into their web interface.

You can browse the project live at cafe-finder.getforge.io/#!/styleguide.

A great idea if you do deploy your prototype for extended feedback is to use a widget like usersnap to collect feedback from anyone visiting the prototype4.

This section includes steps for installing the tools you need to get going with Vue, and how to use the github repository to follow along with the tutorial activities.

Setting up Vue

Setting up your computer for development in a new language can take a bunch of steps. Don’t worry, this is something you’ll only need to do once.

Here’s a list of the things we need to do:

  1. Download and install Xcode.app from iTunes store
  2. Install Node and npm
  3. Install Vue command line interface
  4. Install Github desktop app (and create account if needed)
  5. Install Atom (or your preferred text editor with syntax highlighting)

Let’s get started!

1. Install Xcode.app from Apple App store

Xcode is for more than just iOS apps, it’s a general-purpose IDE and set of development tools for a range of languages.

We won’t be using Xcode directly, but we need some of the tools that come with Xcode as a dependency for other tools that we’ll be using.

  1. Download Xcode from the App store.
  2. Check that the path to Xcode command line tools are set (Xcode → Preferences → Locations).

2. Install Node and NPM

  1. Download and install Node. I recommend to choose the ‘mature’ version instead of the newer version, but both should be fine.
  2. Because we’re installing an application from the web instead of the Apple app store, you might need to open the ‘Security & Privacy’ tab in Settings to give permission to install Node.
  3. To confirm that node and npm were installed successfully, type npm -v and node -v which will print out a version number if they were installed, or the message command not found if they were not.

3. Install the vue-cli package

You can start using Vue simply by adding a script tag to your html files, but installing the vue-cli package includes some nice tools that help organize our code, and speed up prototyping.

vue-cli is a node package, so we install it from the command line using npm.

  1. In Terminal.app type npm install -g vue-cli. This is asking npm to install the package ‘vue-cli’ and make it available globally.
  2. Depending on how your OS X account is setup, you might need to type sudo npm install -g vue-cli which is the same command, but giving npm access to superuser permissions. You’ll be promoted to enter your OS X password.

4. Install the github desktop app (for version control and collaboration)

Git is a command-line tool for version control that allows a team to collaborate on text files, track changes, and rollback to earlier versions if needed.

We’ll use github to store our repository online, and use their desktop app instead of interacting with git through the command line because it’s a lot easier.

  1. Install the desktop app from desktop.github.com
  2. Create an account on github.com and sign into the app.

5. Install Atom (or your favorite text editor)

Atom is a text editor created for writing code. If you have a favorite editor you can use that instead, but Atom does have some convenient shortcuts with the Github desktop app.

  1. Download and install Atom
  2. Find and install a package that will apply correct syntax highlighting for .vue files (Open Atom → Preferences → Install → search for ‘vue’ and install ‘language-vue’ which should appear as one of the top search results).

That’s it! Your computer is now set up with all the tools you need to make using Vue easy.

Using the tutorial repository

I’ve created a github repository for this tutorial where every activity is available as a commit in the project. You can use this repository to jump around different phases of the project, run the project at these different stages, and explore the code at each stage.

A. Clone the repository

When we clone a repository, it just means downloading a copy of the project onto your computer.

A repository is more than a directory of files, it includes snapshots of the project at different stages of the project, and the changes that were made (additions, deletions, and modifications) to files at each step.

In this sense it’s like a really smart undo, or time machine, allowing us to jump around to see the project at different times (and if we want to revert back to an earlier step).

  1. Go to the cafe-finder repository page on github and find the open in desktop button.
  2. Because we’ve installed the github desktop client, this app will open and prompt you to choose where to save this project.

The Github desktop app should open to show a history of commits within the project. You can click on each commit, expand it to see what files were changed as part of that commit, and see in more detail what changed in that file at that step (text highlighted red shows lines that were deleted, and highlighted green to show additions).

B. Open the project in Atom

One of the nice things about using Atom as your code editor is the close integration with the Github desktop client.

Now let’s actually open up this project in Atom and start making some changes…

  1. Right-click the cafe-finder repository in Github desktop app and select ‘Open in Atom’.
  2. Atom shows the files and folders for this project in the left hand panel, click index.html to show the contents of that file.

C. Jump back to the first step of this project

When cloning a repository, by default we’re taken to the most recent commit that was made. Because we want to start the tutorial at the first step, and then work through the linear series of steps we need to jump back to the very first commit in the repository.

The Github desktop app doesn’t have this feature, so we’ll have to jump into the Terminal to do this through the command line.

  1. Navigate to the first commit in the project (commits are in reverse chronological order so it’s the last in the list).
  2. Click on the gear icon and choose Copy SHA. The SHA is a hash that acts as a sort of bookmark for this commit.
  3. Right-click the cafe-finder repository in Github desktop app and select ‘Open in Terminal’.
  4. Type git checkout and then paste in SHA, and then hit return key.
  5. In Atom, you should see the contents of index.html change as the project jumps back to the state of the project for this commit.

D. Install dependencies

  1. Type npm install and hit return key.

This command starts of a process where npm downloads and installs any packages that we depend on for vue-cli to work (also known as dependencies).

These dependencies are listed in a file called packages.json in our project folder, and as you run this command you’ll see a folder called node_modules be created and a folder added for every package that is downloaded (the terminology is confusing, but for now think of package, dependency, and module as different words for the same thing).

E. Run the project

Finally, we’ll actually run this project, so we can see this project in the browser.

  1. Type npm run dev and hit return key.
  2. Copy the URL that’s presented when the server starts (it should be http://localhost:8080).
  3. Open a new tab in the terminal and type open http://localhost:8080 to launch your default browser.

You can now follow along the activities in the tutorial from this step, and if you get stuck at any step you can always use the git checkout command to jump to a specific step of the tutorial.

Notes

  1. A lot of effort has gone into creating tools that automate the creation of HTML and CSS from the layers of a high-fidelity illustration. What I wish existed was the reverse: A tool that took an existing HTML concept and imported it into layered comp that could then be manipulated.

  2. A good example could be that your company has a rapid development cycles, healthy collaboration between designers and developers, and a culture that promotes experimentation and testing.

  3. The latest of these tools is Adobe’s Project Comet. I encourage you to go view the demo, and get excited by what you see because the outcome is exactly what we’re trying to achieve, but carefully consider investing in learning a specific tool when the same result can be achieved with existing development tools.

  4. There aren’t any decent free tools that support collecting user feedback, so for this you’ll need to pay a small monthly subscription for access to these tools.