Designing declarative APIs

The video of my Piter CSS conference talk “Designing declarative APIs” has been published:

I’m talking about why declarative APIs are great and give examples of their use in my own projects:

At the time of the talk, the new Jouele Pro was still in development. Now it is available.

Thanks to the conference organisers.

 106   2018   Emerge   Jouele   Likely   talks   web

Jouele 2.3

Jouele 2.3

Jouele is a simple and beautiful audio player for the web. Eugene Lazarev has been developing it lately.

Version 2.3 has been released. Jouele now uses Howler (bundled) instead of jPlayer. This change helps use less bandwidth, display the preloader better and get rid of several bugs. The data-repeat feature is now supported on single tracks. When a file is unavailable, Jouele shows this with an icon, instead of just “hanging”. The markup works better in different browsers.

Song example:

See documentation on Github.

 60   2017   Jouele   projects   web

User interface for Mimic 2.0

A web application’s front end (what the user sees) and back end (what happens on a remote server) are often developed separately. If the back end of some feature is not ready yet, the front-end developer is very limited in what they can do.

I’ve designed the user interface for Mimic 2.0, a web developer tool for mocking server responses in a browser. With Mimic, you can develop as if the server was alive. It’s very easy to set up a simple mock. Say, you want to pretend the server responds with a line of JSON:

It lets you set up very advanced mocks, adjusting HTTP headers, timeouts and what not:

The great thing about Mimic is that you don’t need to set up a local server and change request URIs in your application. It works with the existing applications as they are, right in the browser. And you don’t even need to install browser extensions: you just link one script to your application and that’s it.

Read more about the user interface on the project page.

 84   2017   projects   user interface   web

Why are browsers so slow?

I understand why rendering a complicated layout may be slow. Or why executing a complicated script may be slow. Actually, browsers are rather fast doing these things. If you studied programming and have a rough idea about how many computations are made to render a page, it is surprising the browsers can do it all that fast.

But I am not talking about rendering and scripts. I am talking about everything else. Safari may take a second or two just to open a new blank tab on a 2014 iMac. And with ten or fifteen open tabs it eventually becomes sluggish as hell. Chrome is better, but not much so.

What are they doing? The tabs are already open. Everything has been rendered. Why does it take more than, say, a thousandth of a second to switch between tabs or create a new one? Opening a 20-megapixel photo from disk doesn’t take any noticeable amount of time, it renders instantaneously. Browsers store their stuff in memory. Why can’t they just show the pixels immediately when I ask for them?

You may say: if you are so smart, go create your own browser — and you will win this argument, as I’m definitely not that smart (I don’t think any one person is, by the way).

But I remember the times when we had the amazing Opera browser. In Opera, I could have a hundred open tabs, and it didn’t care, it worked incredibly fast on the hardware of its era, useless today.

You may ask: why would a sane person want a hundred open tabs, how would you even manage that? Well, Opera has had a great UI for that, which nobody has ever matched. Working with a hundred tabs in Opera was much easier back then than working with ten in today’s Safari or Chrome. But that’s a whole different story.

What would you do today if you opened a link and saw a long article which you don’t have time to read right now, but want to read later? You would save a link and close the tab. But when your browser is fast, you just don’t tend to close tabs which you haven’t dealt with. In Opera, I would let tabs stay open for months without having any impact on my machine’s performance.

Wait, but didn’t I restart my computer or the browser sometimes? Of course, I did. Unfortunately, modern browsers are so stupid that they reload all the tabs when you restart them. Which takes ages if you have a hundred of tabs. Opera was sane: it did not reload a tab unless you pressed Reload. To show you the tab, it just reopened everything from its disk cache. Which took a couple of seconds.

Modern browsers boast their rendering and script execution performance, but that’s not what matters to me as a user. I just don’t understand why programmers spend any time optimising for that while the chrome is laughably slow even by ten-years-old standards.

I want back the pleasure of fast browsing.

You should follow me on Twitter, here

 569   2016   browsers   programming   rants   software   web

The “Buy” button should always work

Here is one lesson I have learnt working on Envy, a cool Hawaiian car rental.

On a car page, there is a yellow price tag with a “Rent” button:

The “Buy” button should always work

A typical way to get to this page is the following. On the front page a client chooses the desired rent dates, clicks “Find”, then selects from available cars. It is possible though, that by the time the client selects a car, somebody else books it already. Or the client reloads the car page in a couple of days, and the car is gone. One way or the other, a client can end up on the car page with the pre-selected rent dates, for which the car is no longer available, and they won’t be able to rent it.

Also, on the front page we show the best cars we have. A client can click any of them and get to its page, having skipped the dates selection altogether. In this case, the dates won’t be specified, and the client also won’t be able to rent the car. We didn’t want the client to be confused by the disabled “Rent” button, so in addition to the front page, we put the dates selectors to this price tag itself.

I presented the design of the car page to Ilya Sinelnikov (co-creator of Envy) and was talking about the price tag.

I said, we didn’t like that the “Rent” button is disabled sometimes: the website is there for the people to rent cars. But how can you rent a car which is taken by someöne else? At first, we thought that we could automatically change the dates to the nearest available ones. But it can result in a disaster: what if the client doesn’t notice the change, pays for the rent, comes to pick-up the car, and learns that we don’t have it? I said, we were also thinking about some tool to explain the problem and help the client change the dates, but there was no chance to make it on time for the website launch. So, I said, for now I suggest just disabling “Rent” the button in this case.

Also, I said, a car could become unavailable while the clients looks at its page. Therefore we needed to re-check the availability after the “Rent” button is pressed, and inform the client of a problem, if it occurs. For now, I said, we’ve designed this error page. In the future it would be better to suggest a date change or offer another car. But this is also not going to be implemented by launch...

Ilya interrupts: “To hell with the dates, let’s just make the button always enabled.”

What? There can be no car for the client when they come.

“The client is willing to pay us money”, Ilya says, “and you prevent them from it by disabling the button. This is inefficient. Let them pay, and we’ll sort it out”.

And then Ilya enlightens me. Envy as a business must be able to sort this out anyway. It is possible that a booked car is not available for the client, say, if the previous client breaks it, or whatever. In order to make the client happy, Envy offers them a better car for the same price.

For Ilya, it all appeared as if I was trying to stop his client from paying him money with my UI. But from the business perspective my UI consistency hurdles are insignificant. Dates have accidentally overlapped? Oops, sorry, here’s a Mercedes instead of a Ford, no big deal. In the worst case, if there’s a super-picky client who won’t take anything but the very car they’ve chosen on the website, we’ll return the money and apologise.

So we made the “Rent” button always enabled. If by the time the client clicks it, the car becomes unavailable for the selected dates, the manager gets a notification about a problem, and it is their job then to contact the client and agree on a new car or dates. And if the dates are not selected at all, clicking “Rent” moves the focus to the dates fields and opens the calendar, so that the client knows what to do.

Principle: the “Buy” button should always work.

 201   2016   Bureau   design   service design   web   work
 34   2016   Jouele   projects   web

Jouele 2.0

Jouele 2.0

Three years ago I made Jouele, a good audio player for the web.

Eugene Lazarev has made version 2.0. The player has dropped the skeuomorphic look and got even nicer. It is now easier to customize the colours. The new version has dynamic initialisation, and is a jQuery plugin with an API (these are presumably good things). I have installed it on my website.


 50   2015   Jouele   projects   web

Emerge.js with a new spinner and scrolling support

In 2013, I’ve released Emerge.js, a framework for coordinated page loading:

Normally, when a complex web page is loading, images appear in random order, causing unpleasant flashing. To replace it with nice and coordinated animations, programming is required. Emerge.js simplifies the task by removing the need to write any JavaScript code. The framework uses a declarative approach, where you specify a desired behaviour for each element and do not think about the implementation.

See also the introductory blog post. I’ve since updated it with new features.

Spinner stuff

In version 1.1 I’ve added a built-in loading spinner. Emerge.js no longer requires spin.js for that. But you can use a custom spinner, including spin.js, if you like.

As before, to display a spinner while an element loads, use data-spin="true". Use the new attributes data-spin-size, data-spin-color, data-spin-direction to control the appearance of the spinner (see documentation on the Emerge.js’s page).

To use another indicator (i.e. one of the nice ones by Sam Herbert) just wrap it into a named div and tell Emerge.js to use the contents of the div as an indicator:

<div id="cool-spinner" style="display: none">
  <svg> ... </svg>

<div class="emerge" data-spin-element="cool-spinner">
  <!-- while this loads, the cool spinner will be displayed -->

To use spin.js, make it run inside your div and align as necessary:

<script src="/path/to/spin.js"></script>


<div id="spinjs-spinner" style="display: none">
  <div style="position: absolute; left: 50%; top: 50%; margin: -8px"></div>

  var spinner = new Spinner ({
    lines: 12,
    length: 4,
    width: 2,
    radius: 8,
    corners: 0,
    rotate: 0,
    color: 'rgba(96, 96, 96, .75)',
    hwaccel: true
  spinner.spin ($ ('#spinjs-spinner div')[0])


<div class="emerge" data-spin-element="spinjs-spinner">
  <!-- while this loads, spin.js will be displayed -->

Scrolling stuff

In Version 1.2 with the new data-expose attribute you can make an element emerge only when the user scrolls enough for it to get into view.

<div class="emerge" data-expose="true">
  <!-- this will emerge only when within view -->

Of course you can combine it with other attributes and effects. This div will emerge with a zoom effect in a quarter second after the users scrolls enough for it to become visible:

<div class="emerge" data-effect="zoom" data-hold="250" data-expose="true">
  <!-- this will emerge quickly after getting into view -->

For an example, see my Projects page. The data-hold value varies slightly between elements there to add a nice randomness effect.

Update for free

If you’ve bought Emerge.js, you get the updates for free. Drop me a line if you have any questions.

 64   2015   Emerge   projects   web

Hand holding as a web design approach

To create a successful web page about a product, try hand holding. In addition to saying what product you have, help the reader start using it: explain, guide, convince, clarify, warn.

Let’s say you are a bank and a you have a page about your savings account options. There are people who don’t know what deposits are or why they might want one. Others are afraid of having large amounts of cash on them and don’t want to go to the bank with it. Or they are just unsure which office to go to, what documents to have and how long the thing will take. Your job is to alleviate their anxiety, to raise their self-confidence and to help them make an informed choice. To get clients, help people become clients by hand holding. Explain why a deposit may be useful. Visualise the interest rate. Say how to transfer the money online from another bank. Show the nearest office on the map (include the business hours). Publish the contract with useful comments on the margins. Acquaint the reader with your managers.

Or suppose you install windows and you have a page with options for fittings and glass coating. Well, most people have no idea on how windows are installed. Or even what elements they consist of. What should I consider before ordering windows? How to gauge a window opening? Who will disassemble the old windows? How long will it take to do the whole house? Can this be done in winter? What if a new window does not fit? Can I pay with a Visa? To get clients, help people become clients by hand holding. Explain the whole process from step one to step done. Connect the options to real-life cases (the inner windowsill for kitchen could be made of a heat-resistant material). Say in advance what can go wrong and how to avoid it. Publish the contract with useful comments on the margins. Acquaint the reader with your managers.

Or maybe you are a web hosting provider and you have a page that lists services, plans and options. This may be good for an experienced web administrator. But if someone makes their first website, they probably don’t even know that a domain name and web hosting are separate services. They have no idea if they need CGI, SSL or mod_whatever. They have no clue how to make email work. To get clients, help people become clients by hand holding. Help them figure out which set of services will fit them depending on why they came. Explain what steps are necessary from subscribing to a hosting service to opening the website. Help understand and configure DNS, choose and set up an FTP-client. Publish the contract with useful comments on the margins. Acquaint the reader with your support team.

Yes, the answers can be found online. But if you rely on that, you didn’t do your job well. Your website should work like an experienced and attentive manager, not like an indifferent price tag.

Many people suffer from professional deformation: they think everybody understand their technical terms and work principles. I’ve even heard an opinion that such “hand holding” shows disrespect to a client by treating them like a child.

This is an error. Everybody likes feeling taken care of. If your hand holding feels patronising, your are just not caring sincerely enough.

 73   2015   design   service design   web

A proposal for custom website loaders: loading.html

In a browser, when you enter a website address and press Enter, the first thing you see is white screen — no matter how fast your internet connection is. When you launch an app on an iPhone, you see the app immediately — no matter how old your phone is and how slow the app is. The trick is that every iPhone app includes a screenshot of its own initial state. Usually it is the app’s first screen without any content.

The browsers could copy the iPhone’s behaviour to improve the perceived speed of the web. In addition to the real page, a web server could serve an HTML file with a temporary content to show while the real page is loading. We’ll call it loading.html, but it could be anything pointed to by a link tag.

When the user goes to a site for the first time, the browser loads it in a regular manner. But if it figures out loading.html is available, it downloads the file and saves it locally. When the site is open again, the browser renders loading.html immediately and then replaces it with the real content when it becomes available.

This is not caching: browser shows loading.html while, not instead of loading the real page. And it will reload this file when it changes, like any other resource.

The difference between nothing and something is huge: immediate feedback, even approximate, is one of the main things that make user interface great. Enter:

A proposal for custom site loaders: loading.html

The following aspects of loading.html should be considered:

  • External resources. It seems sensible to disallow usage of any external resources for the file. They defeat the purpose of the file: the browser should not spend any time loading images or fonts for this temporary screen (which, hopefully, will be visible for only a second). The browser could cache those, but this may become a debugging nightmare. Embed all the styles, scripts and images — or make do without them.
  • File size. Since a browser should store this file for every site you’ve visited, the file should be small. Also, its loading should not tax the visitors who open your site only once.
  • Interaction and continuity. Interaction with a page that can vanish and get replaced with another one any moment seems strange. At first I though that it should be completely prohibited: no links, no listening to JavaScript events. But then I thought, what if I put a site’s menu in loading.html? If a user clicks a link, the browser could switch to loading it (it, by the way, could have its own loading.html, see also Scope). But badly implemented this could be frustrating. Say, a user is typing a search query into an input of loading.html when it gets replaced with a real page. The browser must make sure the typed letters are not dropped and the caret position is maintained.
  • Progress information. It would make sense for loading.html to want to display a spinner or a progress bar itself instead of relying on the browser. For this to work, the progress information should be available to it. A way to implement this would be with an event sent to the page, i.e. onLoadingProgress (in which case disallowing all events is not an option).
  • Location. From the point of view of the scripts on the loading.html page, its location should probably be the same as for the real page it’s temporarily replacing (even though in reality, obviously, loading.html was loaded from another URL).
  • Cookies and localStorage. These should probably be available to loading.html as for the real page also. A use case would be showing the name of the signed-in user right on the loading.html page.
  • Scope. A loading.html page might want to specify the scope of real pages it works as a loader to: only the one it is linked to, a range of pages, all pages on the given domain name.
  • Expiry. A loading.html page might want to specify its expiry date.
  • The switch. When should loading.html be replaced by the real page? Waiting for the full page to load is surely not optimal. Perhaps, a browser should use the same heuristics it uses now to start displaying a page when following a link. But I would consider giving a loading.html-aware pages some additional control over it.

I don’t have experience with Offline Web Applications APIs, but going by the description, I assume at least some of the described behaviour could be implemented with them. It would, however, be too complicated for anyone to bother.

This feature will probably be abused by some designers to show splash screens and ads. That’s not a problem. On the iPhone, some apps also show splash screens, and though this sucks, in no way is it a reason to remove the feature (actually, if we remove every feature that has a capacity of being abused, we’ll remain with nothing).

I’ve long been concerned with how web pages look and behave during loading, as you may have guessed looking at Emerge.js (just updated, by the way). There is a lot we can do as front-end developers. But to make things significantly better, help from the browser vendors would be required.

 127   2014   browsers   Emerge   web
Earlier Ctrl + ↓