pushState Enabled Twitter

A case-study (with a working implementation) of extreme progressive enhancement applied to mobile.twitter.com

Bandwidth comparison


Hashbangs are dead

Late in May 2012, Twitter began migrating its twitter.com site from hashbangs to plain-old-URLs. This was done for a number of reasons, but one of the higher priorities was improving performance, most notably "reducing the time to first tweet".

The scripted page navigation that was facilitated by using AJAX and hashbangs is (will be) replicated by using AJAX and history.pushState() (on browsers that support it).

What's still wrong with twitter.com?

How could it be fixed anyway?

Funnily enough, twitter already has a site that uses plain-old-URLs and provides optimal time to first tweet - mobile.twitter.com. This site also:

What if Twitter had applied a mobile-first / content-first strategy to the twitter.com upgrade, using mobile.twitter.com as the starting point and relying on progressive enhancement in the browser to provide a richer UI?

This article provides a case study of how this could be done. There is also a javascript bookmarklet which implements (as near as possible) the approach detailed here - see the meeko-twitter page.


What are we starting with?

All of the content pages on mobile.twitter.com have the similar structure and appearance:

For instance:

Home page

mobile.twitter.com home page

Account page

mobile.twitter.com account page

Discover page

mobile.twitter.com discover page

What are we aiming for?

twitter.com has corresponding pages, but with a richer UI plus page-specific auxilliary content.

There are, however, only a few variations on page-layout and, conveniently, all the pages on twitter.com can be represented by one page template consisting of multiple panels, each of which may be separately hidden (or populated and revealed) as appropriate.

The following picture illustrates this single page-template, with labels on various panels (and also some source directives which I will explain later).

Single page template for twitter.com like UI

The goal of our progressive enhancement is that whenever the browser navigates to a page

  1. this page-template is loaded as the content of the window (with all panels hidden).

  2. the main panel is populated with the main-content of the page and shown.

  3. appropriate auxilliary panels are populated and shown.

(If the navigation occurs with pushState + AJAX support then the template is already loaded and step #1 is skipped. See later in the article.)

What changes need to be made on mobile.twitter.com?

This suggests adding something like the following code to the <head> of each page:

<link rel="template" type="text/html" href="/template.html" />
<script type="text/javascript" src="/loader.js"></script>

No changes are necessary to the <body> of pages, however there are some pages which have main-content that we don't want to be placed inside the main panel.

The following pictures illustrate this by outlining the page-content desired for the main panel (red) and secondary content (green).

Home page

mobile.twitter.com home page - scraped

Account page

mobile.twitter.com account page - scraped

Discover page

mobile.twitter.com discover page - scraped

This could be handled by changes to the server-generated pages, but since our enhancement is extracting the relevant content anyway, it is trivial to rearrange the page when it is received to move the secondary content outside of the main-content container.

How are the auxilliary panels handled?

After the main-content is inserted into the main panel the auxilliary panels are checked for relevance to the current page. If the panel is irrelavent it is hidden (if not already hidden), otherwise:

What about popup dialogs for composing / replying-to tweets?

While posting tweets to mobile.twitter.com will have a specific format, the overall process of wrapping a form in a dialog popup and serializing the form-data to post with XMLHttpRequest is hardly novel and is left as an exercise to the reader.

Example: Home page

When the browser navigates to the home page (mobile.twitter.com), the following steps should take place:

The final state of the page will look something like

mobile.twitter.com home page - decorated

pushState / onpopstate assisted navigation

This is quite simple because most of the work has already been implemented. At this stage of enhancement we don't even need to save state because the page URL completely defines the state of the page. All that is required is:


The obvious advantages of creating a rich UI by progressive enhancement of a content first site (such as mobile.twitter.com) are:

  1. noscript, mobiles and other small-screens are already catered for
  2. all devices can use the one site so URLs can be shared to all devices
  3. the generation of content pages is the same for all devices, simplifying development and reducing maintenance

Performance of this approach must be measured of course, but it does have some potential gains:

Another potential benefit of this approach is that it would be trivial to allow different page-templates to be selected from within the browser. The appropriate page-template could depend on


Further Reading


If you have any questions, or if there are errors or omissions in this article, feel free to contact me via the contact dialog on this page.