Thomas Fuchs
Hi, I'm Thomas Fuchs. I'm the author of Zepto.js, of, and I'm a Ruby on Rails core alumnus. With Amy Hoy I'm building cheerful software, like Freckle Time Tracking and Every Time Zone and write books like
   Want me to speak at your conference? Contact me!

Want to rock bootstrapping a SaaS?

September 4th, 2013

BaconBiz Conf 2013 Trailer

Join us at our next BaconBiz Conf—watch the trailer for the last one and leave your email to get all the talk videos from this year as they’re released and be the first to know when we’ll do it again… :)

Handling numerical input in mobile web apps or “A sad tale of two keyboards”

August 30th, 2013

“[These phones] have these keyboards that are there whether or not you need them to be there. And they all have these control buttons that are fixed in plastic and are the same for every application. Well, every application wants a slightly different user interface, a slightly optimized set of buttons, just for it.”
—Steve Jobs, iPhone introduction Keynote, January 9, 2007

I agree with Steve Jobs. However, the state of keyboard customization in mobile web apps is sad.

For our new mobile web app for Freckle Time Tracking I’m looking into ways to have the least possible amount of taps for the user to enter her time. In order to that, I want to tell HTML input fields which keyboard to open. Sounds simple? Read on.

The iPhone and Android phones support various keyboards, among them keyboards specialized in entering text (the “default” keyboard), entering numbers (a keypad with some extra buttons like a comma and a decimal separator) and a phone keypad (which has stuff like “ABC” on the 1 key and a # key).

Now what I’d really like to do is show the user the keyboard that is part of the default keyboard but shows up when you hit the “123” key—a horizontal row of numerical keys like on a real hardware keyboard. The reason for this is that people in Freckle should be able to enter stuff like “15m” for 15 minutes of time, just like they’re used from the “desktop” web version.

Let’s have a look at the available ways to select which keyboard should be shown:

The type attribute

The type attribute can be set to “number” to allow numerical input. (I won’t go into the “tel” type).


Now this actually works nicely on iPhone because I get the default keyboard, but it’s already switched to the screen that you get when you press the “123” key. The best thing is that users can switch back to the QWERTY part and can freely enter whatever they want. That’s exactly what I need because I want the keyboard to emphasize numerical input and expect it as default, but allow other things as well—that is until you try to set the content via JavaScript. If you try to set the value of a type="number" input field to something like “2:00″, no dice. The value is (silently!) not set. Note that adding a novalidate attribute doesn’t change this either.

On Android, it’s yet a different story—I get a specialized keypad with numbers only (and a few special characters). Unfortunately, that doesn’t work for my use case as the user can’t switch from the specialized keypad to the default keyboard.

The pattern attribute

According to Apple’s documentation, setting the pattern attribute to [0-9]* or \d* is “equivalent to using type=number”. Except that these are dirty lies, it actually does something very different—show just a numeric keypad without the possibility of changing back to the default text entry keyboard.


There’s a second problem, perhaps even more serious—there is no API to either know if there is a keyboard displayed currently nor to determine the visible viewport of the mobile web page (the visible content area of the mobile browser minus any space taken up by any keyboard shown). This prevents me from adding my own row of keys that could provide the extra functionality I need (notwithstanding complex issues with browsers losing input field focus when tapping these keys; this can be worked around).

Additionally, the Safari HTML Reference documentation was last updated about two years ago in 2011 and still sports screenshots from the original iPhone. It’s overdue for an update.

Alas, I can’t make this work correctly on either iOS or Android, and will have to default to the normal keyboard and perhaps try to add some of my own buttons, guesstimating the keyboard size and position.

Why is this so hard? Why can’t we have nice things? Mobile web apps seem to be treated as a second-class citizen by both Apple and Google. All I want is to make the user have to work less and be able to use my web app quicker—and be more awesome.

Dear Apple and Google: please allow me to do that.

Slim progress bars for Zepto with zprogress

August 23rd, 2013

Do you like the slim progress bars used by Chrome on Android as well as Safari on [redacted]?

What’s a slim progress bar to do?

  • The progress bar is a 3 CSS pixel high solid color bar, on top of the browser content window.
  • Fades in to indicate activity, usually network requests (Ajax!).
  • While stuff is loading, trickle to the right in animated, small steps. This trickling is actually random and doesn’t indicate real progress. This is to communicate to the user that “something is going on”.
  • Stop at about 80%-90% of screen width if stuff is not finished by then. The trickling can get shorter and slower while it reaches this threshold.
  • When things are loaded, animate the progress bar to 100% width and fade out.

There’s a great library called nprogress out there, but it requires jQuery (it uses jQuery’s animation system). Now, what to use with Zepto? Being lean Zepto relies on built-in CSS transitions and animations, both to save on the lines of JavaScript required and to make better user of battery power (CSS-based transitions and animations stand a better chance of being animated with the GPU, which will save power).

Never fear, here comes zprogress!

This does the same exact thing, but works with Zepto’s animate method. To facilitate GPU-based animation, nprogress uses only CSS transforms and opacity-based CSS transitions (it basically moves an off-screen bar that’s as wide as the screen onto the screen with a translation transform). Using just CSS it adapts to any screen width and will automatically work as expected when the screen orientation is changed. It’s also API-compatible with nprogress, so it’s easy to pick up. It also doesn’t come with several features, e.g. there’s no spinning progress indicator. I find this a) redundant and b) outside of the scope of the pure progress bar.

Zprogress is easy to hack as it’s only about 70 lines of code (including CSS!), so if you need to add features for your web app it’s probably the easiest to just fork it. It’s a one-liner to plug it into Zepto’s Ajax system to have the progress bar globally for all Ajax activity (see the README for details).

Grab zprogress on GitHub!

How many JavaScript frameworks do you need to make a landing page?

August 10th, 2013

The answer to this question is, of course, 0. Zero, nada, zilch.

Here’s the new landing page we made for our Time Tracking Software, Freckle:

Screen Shot 2013-08-10 at 11.10.29 AM

While there is some interactivity going on, there simply is no need to include any JavaScript frameworks. (Note that we DO load in some JavaScript asynchronously, including frameworks, but these are for analytics and A/B tests; for the page itself to load and work the are not necessary. It was only added after we went live and won’t influence page loading speed as explained below.)

Here’s some things the page does that might not be obvious at first glance:

  • Responsive design so it works on phones
  • Screenshots and logos are fully retinafied
  • SVG images for some of the logos
  • Self-serve web fonts
  • Hover over the top area with the piecharts and you see an animated tooltip popping up, just as in Freckle (this is done with just CSS)
  • The “screencast” further down the page is an animated GIF at retina resolution (biggest asset on the page at 386K)
  • The press logos under the plan selection are using webkit-filter to show them in greyscale (hint: add -webkit-transform: translateZ(0) so this works correctly on retina screens on Safari)

Now, you could use JavaScript for many of these things—swapping out images for retina screens, using hosted web fonts that may require a JavaScript-based loader (and another DNS lookup), animating the tooltip, have a Flash and/or HTML5-based, JavaScript-controlled video playing.

But, guess what, browsers these days have a lot of super useful stuff built-in so you don’t need to (and yes, the site will horribly fail on Internet Explorer before version 9, but we don’t target that crowd anyway as Freckle is not compatible with those).

The result? Next to that it obviously loads pretty fast, PageSpeed Insights gives the page a 95/100 score. A reload of the page with a primed cache transfers about 14KB of HTML, but even if the cache is empty, it takes less than 200ms for the DOM to be ready (this is with all extra JavaScript that’s loaded for analytics and whatnot):

  • Freckle (empty cache): 34 requests ❘ 699 KB transferred ❘ 1.90 s (onload: 875 ms, DOMContentLoaded: 196 ms)
  • Freckle (primed cache): 30 requests ❘ 14.2 KB transferred ❘ 1.22 s (onload: 202 ms, DOMContentLoaded: 56 ms)

Here’s a few of our competitors websites loading from empty cache on my fast internet connection (under ideal conditions: latest Chrome, US east coast, 60Mbps, Saturday morning). I won’t give names to protect the innocent:

  • Site A (empty cache): 96 requests ❘ 583 KB transferred ❘ 1.42 s (onload: 1.26 s, DOMContentLoaded: 697 ms)
  • Site B (empty cache): 52 requests ❘ 872 KB transferred ❘ 962 ms (unload: 823 ms, DOMContentLoaded: 571 ms)
  • Site C (empty cache): 104 requests ❘ 1.6 MB transferred ❘ 3.30 s (unload: 3.07 s, DOMContentLoaded: 1.54 s)

Screen Shot 2013-08-10 at 11.57.40 AM

First impressions are important. I strive to have DOMContentLoaded fire as quickly as possible for that warm fuzzy instant loading feeling. If you can keep this under 100ms to 200ms your users will be very happy. For Freckle, we do everything possible to make it load super fast because we know that time tracking sucks and you want to get it done quickly. Software should assist you when you need it but get out of your way as quickly as possible.

How fast does your site load? Do you send people to competitors because you waste time downloading JavaScript you don’t need, or not making sure you download it in the background?

By the by, interested in why we have a long-form landing page? Read Amy’s post on how to grow your SaaS business when it reaches the “Plateau of Doom” (cue dramatic music!).

How to not write a letter to your paying customers

July 7th, 2013

Yesterday, I received an email from Boxee, which was recently acquired by Samsung. It’s one of the worst written emails from a company that I ever received (and I get plenty of email!).

Let’s have a look at what’s wrong with it.

Subject: Boxee team to join Samsung

Well, that’s informative enough but it really doesn’t say why I should care. Well, reading on…

We’re pleased to announce that the Boxee team will be joining Samsung.

Thanks for not saying hi first. Makes me feel really well taken care of. And great that you’re pleased. I still don’t care.

Samsung is the #1 consumer electronics company in the world. They produce all of the screens we watch entertainment on – TVs, laptops, phones, and tablets.

Go Samsung. I still have no clue why I should care, tho.

We’re excited to collaborate with Samsung on how each of these devices can deliver a more integrated TV experience.

What does that even mean? Exactly, it means nothing, except that likely they won’t support the device I BOUGHT from them anymore.

We’re working behind the scenes to ensure there’s minimal impact to your Boxee Box during this process.

TL;DR: We’ll sell not caring, supporting or doing anything with our existing customers as “minimal impact”. Those stupid idiots should have known what they’re getting themselves into. #lolcustomers

The Boxee Box holds a special place in our heart as the first device we built. It was the first living room device to have a keyboard on the back of the remote. It was also the first XBMC-based set top box to be sold at major retailers. It’s the device that really launched Boxee on the world stage, and we want to thank you for being a part of our journey.

Blah, Blah, part of our journey, blah, blah. Note how they’re talking about the product in the past tense. I bought a product from you that barely works and now you’re saying to go fuck myself. Awesome.

Team Boxee

Boxee Customer

Why don’t they just say that their business didn’t work out and they have to close it down and go work for Samsung? I’d be sad for them and understand. Why lie to their customers? Does that make them feel better? Do the VCs require it from them?

Metrics you should actually track in your SaaS business—and how

June 13th, 2013

If you run a business of any kind, it’s hard to get lost in the ocean of data available to you.

What should you track? And how can you act on it? My presentation from BaconBiz Conf in May will help you get started and contains actual actionable advice on how to track data and then act upon what you learn from it.

Bonus: you’ll learn how to produce smooth trend charts that give you the information you need without the clutter!

All the data in the presentation is taken from Freckle Time Tracking (which is the world’s bestest time tracking app, just so you know!).

BY THE WAY, I’m working on an ebook on SaaS metrics (and some JavaScript magic!)—Interested? Sign up for my mailing list!

3 new HTTP headers that we actually need

June 9th, 2013

The World Wide Web has been one of the greatest revolutions in history in how we humans access information. Sadly, the protocol used for transmission of this information (HTTP) lacks an understanding of humans, with maybe the sole exception being headers about preferred languages. But not all humans are the same and not all internet connections and computers are the same either.

“User agents” should be just that, agents of the users, acting in their best interest. Here’s three suggestions to make HTTP better for us puny bags of water:

User-Tech-Savvyness-Score, a new HTTP header with number in the range of 0 (Your Mom) to 1 (Linus Torvalds) that is transmitted from the user agent to the server. If it’s not there, assume the user is not savvy. Browsers could offer this in their settings. A high score would indicate that users know the jargon and the workings of the intertubes—and user interfaces can reflect that (for example, no need to explain what a URL is for the millionth time).

CPU-Utilization, a new HTTP header that provides an average of CPU load over the last minute or so—ideal to avoid burned laps by those auto-loading videos and Canvas visualizations.

Bandwidth-Average, a new HTTP header that gives an average of the network bandwidth that was available to the browser in the last few minutes (in bits/s), so we can finally deliver assets that are more tailored to the user. How awesome would it be if we can easily decide if we should preload videos or maybe not load those custom fonts and help improve user sanity.

I was going to propose User-Likes-Autoplayed-Background-Music, but we all know the answer to that.

In any case, chances that these headers get implemented are slim—my point is to not forget that your content is consumed by human beings.

Be nice by building fast-loading, good-looking, usable sites. Don’t do on your site what you don’t want to be done to you on sites you visit.

Embedding Canvas and SVG charts in emails

April 30th, 2013

In our app Freckle Time Tracking we’re sending out weekly reports to users by email, reporting to them what they achieved last week.

Our emails not only include a report, listing all entries they logged, but also our “Mini-Pulse”, a graphical representation of how much they worked for each project.

Here’s how a typical email we send out looks like:

Freckle Time Tracking weekly report

Now, generating a table and styling it for the HTML email is (relatively) easy, and beyond the scope of this article, but let’s have look at the charts in the email. We already generate the Mini-Pulse graph in our web app—we use an ancient version of Raphael.js to generate SVG, and this gets the job done nicely (SVG works on practically every modern browser, and Raphael falls back to VML on older Internet Explorer versions). Of course, you could use Canvas or any other HTML supported by WebKit just as well.

This is all great in your web browser, but not for emails. First off, obviously, JavaScript
is disabled in HTML emails, so we can’t use that to generate the SVG on the fly; moreover
SVG only works in a handful of email clients.

The only image formats that reliably work in HTML emails are GIF, PNG and JPEG, which means we have to dynamically generate such an image containing the charts and refer to it from the email.

There’s two possible ways to do this:

  1. Reimplement the logic and rendering with a tool specifically made for generating chart images
  2. Reuse the existing JavaScript/SVG code in a headless web browser and make “screenshots”

We chose to reuse the code we have, so we can easily adapt and extend both the web app and the HTML emails in the future (plus no need to learn yet another tool!).

A great way to create screenshots of the graphs is to use PhantomJS, which is a headless WebKit with an API that has support for taking screenshots.

We also have the following requirements for our report emails:

  • Don’t generate the Mini-Pulse if the email is never opened, to conserve server resources
  • Cache the generated image once the email was opened once
  • Securely serve the image and use encrypted URLs with embedded authentication (the user the email was sent to may no longer have permission to access Freckle at the time the email is opened)
  • Charts should be retinafied (your HTML emails are retinafied, are they?)
  • File size of image should be small so it loads fast on mobile email clients

To fulfill these requirements, here’s what happens when a user opens an email that has a chart embedded:

  1. HTML email is shown
  2. Email client or browser accesses URL in the form of
  3. If there’s a cached version of the image serve it and go to step 10, otherwise continue to step 4
  4. Rails app decrypts account ID, user ID, chart type and date range from the given encrypted URL*
  5. Rails app calls internal PhantomJS web service with a URL to call to generate the chart
  6. PhantomJS web service calls the Freckle Rails app internally
  7. Rails app serves Raphael.js, and our chart generation code and the data needed for it. (We use a special, stripped-down layout that only serves the chart and doubles resolution on everything to simulate rendering on a high-density screen (a feature that Raphael.js doesn’t yet directly support).
  8. PhantomJS renders the page
  9. PhantomJS returns a PNG to Rails (the call from step 4)
  10. Rails returns the PNG and caches it into a file (Rails page caching)
  11. Email client or web browser renders the PNG

All this sounds pretty complex, but it’s actually implemented in just about a hundred lines of code.

There’s a few tricky things you have to deal with when installing Phantom.js on a Linux server, such as adding fonts that may not be part of your default Linux server setup, but it’s pretty easy to get going. For Ubuntu 10.04, you can check out this gist with instructions on getting decent rendering quality.

*To accommodate passing parameters along from an HTML email to our Rails app, I’ve released URLcrypt, an open-source, MIT-licensed Ruby library for ‘elegant’ encrypted URLs. Alternatively, you could also use a table the holds tokens, but I find encrypting the account/user id information a more scalable solution.

Zepto 1.0

March 4th, 2013

Party like it’s one-oh! Zepto, the jQuery-compatible JavaScript micro-library for modern browsers, is now available in version 1.0.

Looking back at the first release, back in October 2010, Zepto has come a long way. It’s now compatible with all modern browsers (except Internet Explorer, and yes, it’s easy to fall back to jQuery) and supports complex frameworks like Twitter Bootstrap.

You can grab Zepto at, and contribute via the GitHub repository.

Notable additions and changes in V1.0

  • Zepto is now compatible with Twitter Bootstrap
  • Portable, completely new node.js-based build system
  • Fully automated tests with PhantomJS and Travis CI
  • Removed touch module from default distribution (you can add with our easy-to-use build system, or just load it in addition)

There’s many more additions and bug fixes—see the detailed change log on the Zepto site.

We’re already planning V1.1, for which we will look mostly into code refinements and performance improvements (Zepto is already pretty speedy, as it keeps the loading and parsing time of your site low, especially on mobile devices).

Super-special thanks to all our contributors. You’re the best! :)

Client-side MVC is not a silver bullet

February 26th, 2013

This is an edited repost of a comment of mine on Amy’s blog post about why we shut down Charm.

Charm, as it is, is using Backbone.js, Underscore.js and Zepto on the front-end, and Rails 2.3, Postgres, memcached, redis, resque, and for websockets Sinatra, and a few other things. The front-end is communicating with the back-end via a JSON API.

I’ve come to the realization that this much client-side processing and decoupling is detrimental to both the speed of development, and application performance (a ton of JavaScript has to be loaded and evaluated each time you fire up the app). It’s better to let the server handle HTML rendering and minimize the use of JavaScript on the client. You can still have fast and highly interactive applications, as the new Basecamp shows—letting the server handle most stuff doesn’t mean that you have to cut back on cool front-end features and user friendliness.

I argue that all these newfangled libraries are actually detrimental to the user experience in some ways, as they lock you into certain patterns (it’s hard do to things the authors didn’t anticipate) and if you use something like Ember (which we didn’t), it’s even worse as all applications using it practically look the same (many people choose using Twitter’s Bootstrap library, for example).

We’ve spend a lot of time getting Backbone to work properly, and the ease-of-use quickly deteriorates when your models get more complex. It’s a great choice for simple stuff, but email is far from simple. We also had to add yet an other extra layer of processing to generate “ViewModels” on the server because the normal Rails serialization of objects wouldn’t cut it.

What you end up with is building a layer cake that doesn’t add any value and slows down development. Especially when you’re starting out and need to stay flexible you don’t want to have too much code around—and Rails is great for that, but… adding a JSON API layer and basically a second application that runs on the client is annihilating this advantage for you.

All in all, my current recommendation for SaaS-type web apps is: Rails 2.3 (or Rails 3.2 if you prefer), a Postgres database, as much HTML generation on the server as possible and augment that with RJS (Rails’ mechanism to push JavaScript snippets to the client that get eval’d). This allows for direct re-use of server-side templates, and it’s simple, and works well. As an added bonus, keeping things on the server allow for much better error and performance monitoring and thus quicker turnaround for fixes. There’s also a lot of great stuff in this direction coming up in Rails 4 (like Turbolinks, a sort-of-successor to PJAX, which is a handy replacement for RJS if you don’t like it).

Alas, keep it simple and don’t repeat yourself.