Raspberry Pi Quick Start


Note: If you don’t see the scripts appearing inline, try refreshing.

Last night, I needed to re-image the SD card for my Raspberry Pi to get things setup from a clean state. It’d been a few months since I initially did it, and couldn’t remember exactly what I’d installed, or what config changes I’d made, so I figured I’d document things a little better this time. So, here they are. I’ve pushed all of the scripts and config files up as a few Gists on GitHub to make it easier to edit or change them later.

Step 1 – Create the initial disk image

  1. Download the latest Wheezy image from http://www.raspberrypi.org/downloads
  2. Create the image
  3. In RaspConfig, set:
    • Expand the File System
    • Change system password
    • Set localization options, including locale, timezone, and keyboard layout
    • Set machine name
    • Enable SSH

Step 2 – Setup the Wireless Network

  1. Log in as pi
  2. Run: sudo nano /etc/network/interfaces
  3. Replace the existing content with
  4. Reboot

Step 3 – Create the primary user account

  1. Login as pi
  2. Run curl https://gist.github.com/petele/6346707/raw/create-user.sh > create-user.sh && chmod u+x create-user.sh && ./create-user.sh

Note: You’ll probably want to fork this file since you might not want your user name to be pete ;)

Step 4 – Install & Configure Software

  1. Login as newly created user
  2. Run curl https://gist.github.com/petele/6347546/raw/go.sh > go.sh && chmod u+x go.sh && ./go.sh

Note: You’ll probably want to fork this file since you probably don’t want my GitHub config settings ;)

This script will download the config files from https://gist.github.com/petele/6347546 As part of the setup it will:

  • Update all current software
  • Install new software including Lynx, Apache, VSFTPD, Avahi, Python Setup Tools, OpenSSL, RPIO, sleekxmpp, requests and a few others
  • Configure Git
  • Configure Avahi
  • Enable autologin on the console and run ~/login.sh for every user at login
  • Configure VSFTP, Apache (though it doesn’t properly configure SSL yet), etc…
  • Seriously loosen security settings in Lynx – I need this for the Google Voice stuff in my Home Automation stuff, so use this piece with extreme caution!

There you go – you’re Raspberry Pi disk image is ready to go!


A web UI for my Pi


My project this weekend on my home automation system was two-fold, first I wanted to clean up the code and make it a bit more object oriented, but I also wanted to add a web interface that is accessible outside my apartment.

Home Automation Web InterfaceThe largest part of the weekend was spent re-architecting things. Now, each component is effectively self-contained, so it will be easier to add or remove components later and making it easier for other people to use. Once that was done, I dug into the web interface. The Pi does a POST to an AppEngine app every 30 seconds (configurable) with the status of all of the devices lights, air conditioners, door, even the Harmony remote. Since the data changes often, is less than about 10k and I don’t need it stored for any considerable length, I decided to just store it in memcache to make retrieving it faster.

On the client side, I wanted to emulate the look of the Targus Keypads that I’ve got throughout my place acting as light switches, which is why you see the layout as it is. Across the top is the status of the different devices, for example the state is AWAY and the front door is closed. Both the living room (LR) and bedroom (BR) air conditioners are off, the temperature inside and out is 81° and the amp is off.

The buttons control things in the apartment, the red and blue buttons are modifier keys that affect the gray buttons. For example, pushing Off then Kitchen turns the kitchen lights off. The plus and minus keys only affect the air conditioners right now, though they used to also dim the lights. The buttons show as depressed when that item or set of lights are turned on.

Right now I’m simply doing an XMLHTTPRequest on a setInterval to refresh the data, but I’m planning to modify it to use the Channels API in the near future which will help to eliminate some of the existing lag. I’m also trying to decide if it’s worth adding a live webcam view, not sure I’d really use it, so I’m thinking not, but who knows.

The next part of the project is to solder up the Adafruit RGB Negative 16×2 Keypad Kit and turn that into the alarm clock beside my bed. Not only would it wake me up in the morning, it would also turn the lights on and turn the stereo on to FM radio.

Image courtesy of Switched On Tech Design (www.sotechdesign.com.au)

Home Automation For Geeks


I’ve always had a fascination with home automation systems, things that make your life easier and computers that do the stuff that I’m too lazy to do. In college, I had my tiny little apartment in Ottawa all wired up with X10 and this weekend, I “finished” my most recent creation. Though honestly, is it ever really done?

philips-hue-lightbulbsIt all started a few months ago when I picked up a set of the Philips Hue light bulbs – they’re amazing. LED light bulbs that are fully addressable and programmable via a simple to use REST API. The biggest problem I had with them was that to really use them, you had to leave the light switch On and turn the lights on and off via the app. But it gets to be a small pain in the butt if you have to pull your phone out of your pocket every time you want to turn a light bulb on or off.

The Kit

Okay, so what’s it do?

The keypad beside the front door controlling the apartment.

The keypad beside the front door controlling the apartment.

The Raspberry Pi is effectively the brains of the apartment, it keeps simple state, and sends commands to the lights, the iTach and the Harmony hub. The keypad are placed throughout the apartment and act like multi-function light switches. The zero key and the enter key have special meaning though, either putting the system into Away mode or Home mode. Away mode is just a simple macro that turns all of the Hue lights, uses the iTach to turn off the air conditioners off, shuts the TV and stereo off via the Harmony Hub, and then waits until the front door opens again. When the front door opens, a magnetic door switch saves me from having to hit the Home button which runs another simple macro to turns the lights on, and depending on both the inside and outside temperature, turns the air conditioners on. Oh, and it also turns one of the lights in the living room purple when I have an unread message on Google Voice.

Building out the system

100px-Raspberry_Pi_Logo.svgBuilding out the system, some parts were easier than others. The API for the Philips Hue lights, awe-some! The iTach to control the air conditioners, it was good once I figured out how to teach it IR commands. Google Voice, yah, there’s no API there – that required a little thinking. And the Harmony Hub, there’s no published API for the Harmony Ultimate Hub, and wow, that one sucked.

My original plan was the write a Chrome Packaged App to handle the lights, and run a few USB numeric keyboards around my place. I figured the cost of leaving a Chromebook running 24×7 would be acceptable with the energy savings I was getting from the lights. But, I kept hitting a single and pretty simple problem, I couldn’t keep the Chromebook from locking. I could prevent it from going to sleep, but it still locked, leaving the the USB keyboards useless, since all they could do was type passwords into the machine. So, I pulled the Raspberry Pi I ordered months ago out of a drawer and started fiddling; within a few hours I had a working prototype – I was stoked.

The un-official Google Voice API

google-voice-logoTo be clear, there isn’t a Google Voice API available to developers (boo!), though there are a few good libraries out there that are worth checking out. Sadly, if you have two factor authentication turned on, none of them work since they depend on sending your username and password to Google and doing some unholy magic to log in. And if you don’t have two factor turned on, please go turn on two factor authentication RIGHT NOW. I’ll wait. No seriously, I’ll wait.

I was pretty resigned to not being able to integrate a new message indicator to the system after spending a few days trying to figure out if there was any way possible around the two factor stuff, or if I could somehow figure out how to make a web request with the right cookies. That is of course, until I was reading the history of browsers, and was reminded of Lynx, the first browser I used. Did it still exist, would it work? Would it run JavaScript? The answer is yes! Sure enough, I installed Lynx on my Pi, and then tried logging into Google Voice. I figured if I could log in, I should be able to somehow scrape the results. Sure enough, it worked. Now to figure out how to scrape some results!

After a little searching and some Chrome DevTools digging, I found Google Voice has a JSON end point that will give you a simple JSON object with message counts:


  "unreadCounts": {
    "all": 3,
    "inbox": 1,
    "missed": 0,
    "placed": 0,
    "received": 0,
    "recorded": 0,
    "sms": 0,
    "spam": 28,
    "trash": 0,
    "unread": 1,
    "voicemail": 3
  "r": "SomeMagicCodeHere"

And BOOM I was off! Unfortunately, it means I have to fork a process, start Lynx, request the URL and then parse the result every time I want to check if I have new messages. And my cookies do expire so I have to log back in every so often to re-authenticate, but it’s better than not having any reporting at all!

IP to IR with the iTach

itachA while ago, I came across the iTach IP 2 IR controller, it’s an interesting little device, I think mostly meant for high end home automation systems, but it wasn’t that expensive and I figured I’d give it a go. It’s pretty simple, it has a network jack, and three 1/8” jacks on the back. The 1/8” jacks connect to IR emitters that you can either place in the immediate vicinity of a device, or connect an IR blaster and just put in the room. The manual is pretty thorough for it, except the left out all of the important intro stuff, like the difference between a blaster and an emitter, or where the IR learning port was. Oh, and they don’t have a Mac app, so you need to grab one from a third party app to learn commands.

Once I got this guy somewhat figured out, the rest was pretty easy. It sends out regular UDP multicast packets so you can find it on the network, and then you communicate with by opening a TCP socket and sending an IR command to one of the three IR ports.

For example, to set the bedroom air conditioner to 72°, you’d connect to the iTach on port 4998 and send:


The sendir part is pretty self explanatory, followed by 1:3 which tells the iTach to send it to the third IR port on the device. I guess some of their devices can have multiple addresses, explaining the first 1. If all goes according to plan, it should then respond with:


I mentioned the system turns the air conditioners on depending on the inside and outside temperature. I used the DS18B20 temperature sensor from Adafruit and followed their awesome tutorial for setting it up. For the outside temperature, I check a weather station in Brooklyn (it’s appearently closest to my place) via WeatherUnderground. Their API is free to use and super simple if you’re just using it for a personal project and not hitting it very hard.

Harmony Hub API

logitechThe crowning achievement came this weekend when I figured out how to query and address my Harmony Ultimate Hub. Logitech doesn’t make an API available to developers, and in some ways, I don’t blame them – Harmony remotes are pretty complex and there’s a lot of state and other stuff involved. But that wasn’t going to stop me.

If you’re not familiar with the Ultimate, it’s pretty sweet, not only does the remote control everything, there’s a little ‘hub’ that sits in your living room and allows you to use your phone or tablet as an additional remote anytime you’re on your network.

Sadly, searching for Harmony Hub API at the time revealed nothing useful, I tried up, down and ten ways to Sunday to see if anyone else was trying to do what I did. I couldn’t imagine I was the only one! But nothing. So I did what any developer would do, first I port scanned it (it’s got an open port on 5222, and 8088). I tried my damn’est on port 8088, it responded to HTTP POST requests only, but I couldn’t ever get a useful response. Then I hooked up a packet sniffer and tried to see what was going on with the app. Nothing. Nodda.

Ah right, the wireless network I have setup, was preventing my Mac from seeing packets sent from my phone to the hub. Grrr! Okay, share the Mac’s network and then try again. This time it can’t find the hub. Right, different subnet. Long story short, connect to hub, switch network, now I can see a few packets. Great, so now I can see a few packets, let’s do a few searches to see if anyone has posted about:


Again, BINGO! A GitHub repository called pyharmony, complete with a great protocol guide and working code. The API uses XMPP, which makes sense when you figure the hub potentially needs to update multiple devices with it’s current state in near real time. While I would have much preferred an REST API, I figured I could work with XMPP.

I grabbed the code, installed the pre-reqs, then ran it. Queue sad trombone sound. Didn’t work, well, it connected but then hung while trying to get the session token. I went back and forth with the other developer a few times, compared outputs, and then realized, we were dealing with different hubs.

So this weekend, back to the WireShark I went, this time capturing everything, and sure enough, the login credentials are subtly different, once I updated the code and used the correct login credentials, it worked like a charm. Sadly, my credentials don’t work on his Hub, so we still need to figure out how to do proper device detection and use the appropriate credentials.

You can grab my forked code for pyharmony at https://github.com/petele/pyharmony/, which includes the credentials for the Harmony Ultimate Hub. If you’re using one of the older Hubs, grab Jeff’s code. I’ve also added a few additional functions to my fork that aren’t in the original, including getCurrentActivity and startactivity.

In my home automation system, the Away macro and the Bed Time macro both check the current activity and if the system is on, turns everything off by calling startactivity with the activity ID -1. The getConfig API returns a JSON object with all of the info about your system, including the activity IDs for everything you’ve programmed into your Harmony. Obviously I could add a bunch more functionality to this, but that’s for another day.

Energy Efficient

Energy-Efficient-HomesTalking to some of my co-workers about the system, they were a little concerned about the power consumption of leaving the Pi on all day every day and if that would eliminate the benefit of the Hue lights. As I was wrapping things up this weekend, I pulled out my trusty Kill-a-watt, and did some quick measurements. The Pi uses only about 2 watts, 3 if it’s really pushing it. The lights are only about 8.5 watts each, and since the air-conditioners only come on when needed, I’m being smarter about power there too! So overall, I’m pretty sure that this will save me a little money in the long run.

Home Automation for Everyone

Image courtesy of Switched On Tech Design (www.sotechdesign.com.au)

Image courtesy of Switched On Tech Design (www.sotechdesign.com.au)

There’s a whole bunch more that I want to do with my system, for example a morning alarm, connected to my calendar to make sure I get up in time for any meetings. It could turning the lights on, tune the radio to my favorite station gently turning the sound up (until I get out of bed), the possibilities are endless.

And with the price of hardware like the Raspberry Pi, door switches and such, anyone with a little geek know how can put together a pretty awesome system. Feel free to grab my code and rip it apart and do your own thing with it, it’s not exactly pretty, but I love the fact my apartment welcomes me home at night and says Goodbye when I leave.


High DPI: Tips and Tricks


io13-logoDuring the presentation that John Mellor and I did at I/O this year covering building beautiful websites for high DPI displays, we summarized our talk into about 7 key points.

If you follow these seven simple guidelines, you’ll find your site looks great on any high DPI display.

  • Setting width=device-width means you only have to care about device independent pixels
  • If you don’t set the viewport to width=device-width, or if you use a fixed width, you’re in a world of hurt.
  • The devicePixelRatio on high DPI devices can range from 1.3 to 3 and is about more than just phones or tablets, there are laptops too!
  • Use vector images wherever possible
  • Use @media queries to specify appropriate background images
  • Highly compressed 2x images work well in many cases
  • For sharp canvas images, beware of webkitBackingStorePixelRatio

You can find the video on YouTube at http://youtu.be/alG-UwRWV_U, and we’ve also posted the slides at http://goo.gl/j5Z5W.


Seeing the world through high DPI


At Google I/O this year every attendee got a brand new, beautiful Chromebook Pixel – for many, it was their first high DPI (a so called retina) laptop, and I think many people realized how, um, not so beautiful 1x images look on a 2x screen. In other words, how crappy most of the web looks on a high DPI display.

While there, John Mellor and I gave a talk covering the best practices for building sites that look good on high DPI displays. We covered the theory behind the three different types of pixels and how browsers display 1x images on 2x displays, and the best practices for making sure your site looks great on any device, no matter what if it’s a regular screen or a high DPI display.

You can check out the video below or on YouTube, and we’ve also posted the slides.

Effects of target-densitydpi

Viewport target-densitydpi support is being deprecated


Support for target-densitydpi in the viewport meta tag was recently removed from WebKit and with Chrome for Android moving forward to current revisions on WebKit, this change is now rolling out in Android. This change affects only a small number of sites because of the limited implementation of the target-densitydpi attribute. It brings Chrome and other WebKit based browsers in compliance with the specification and matches the behavior of other modern mobile browsers.

In order to to best understand what’s changed, you need to remember that a device pixel is not the same as a CSS pixel (see CSS Pixels), and that high DPI displays are able to create crisper and sharper images by fitting more device pixels into a smaller space. This means that in order for content to appear at a normal size, the browser treats each CSS pixel as multiple device pixels and the browser scaled up assets and images to fit within the correct number of CSS pixels.

In Android browser and early versions of Chrome for Android, developers could use target-densitydpi=device-dpi viewport value to force the browser to make a CSS pixel the same size as a device pixel, which may cause content to appear incorrectly scaled on screen (as seen in figure 1).

Effects of target-densitydpi

Figure 1 – The effects of target-densitydpi
<meta name="viewport" content="width=device-width, target-densitydpi=device-dpi">
Left: Android Browser respects the target-densitydpi setting and causes content to be improperly scaled.
Right: Chrome for Android ignores the target-densitydpi setting.

An Easy, Quick Fix

In most cases, if your site is affected by this change you can fix it easily by serving the same mark-up (including viewport) to Chrome for Android as you serve to mobile Safari (which never supported target-densitydpi).

Best Practices for Modern Mobile Web Sites

When designing a new mobile site, or updating existing pages, you should use modern techniques for dealing with high DPI displays; including always using <meta name="viewport" content="width=device-width"> and a flexible layout for mobile sites. Remember, device sizes, orientations and pixel ratios vary which means that your site may be displayed on a screen ranging from 320 to over 600 CSS pixels wide.

For more information about best practices for building websites that work well on high DPI displays, check out Reda Lemeden’s Towards a Rentina Web article on Smashing Magazine.

One Other Little Note

While writing up this post, I accidentally did a search for sites that used target-density instead of target-densitydpi and I came across quite a few of them. If you’re using target-density (without the dpi at the end), you can just remove it, it wasn’t doing anything!

Invalid viewport syntax

Meta viewport syntax – comma or semi-colon?


TL;DR: If you’re using a semi-colon to separate values in your viewport meta tag, your site may break! Use a comma instead.

Browsers can be pretty forgiving most days, they do their best to fix our coding mistakes; but it’s a tough job. Most days, they manage to get it right, but trying to fix all the possible error cases is pretty hard. Worse yet, sometimes one browser fixes our code for us, while others don’t.

The viewport meta tag seems to be one of those elements that’s a little bit persnickety. The CSS Device Adaptation spec says the correct syntax uses a comma to separate the values. Unfortunately some sites use a semi-colon, which causes the browser to ignore your viewport settings completely!

Correct Syntax

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />

Incorrect Syntax

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0" />

If you want to see this in action and how bad things can look, use the remote debugger with Chrome for Android Beta to change the comma to a semi-colon in the viewport meta tag on Google.com. The site will suddenly go from looking good, to looking awful.

Good viewport syntax
Invalid viewport syntax

The Developer Tools also warn you in the Console when it comes across an invalid viewport meta tag with the warning: Viewport argument value "device-width;" for key "width" is invalid, and has been ignored. Note that ';' is not a separator in viewport values. The list should be comma-separated.

Go make awesome, but use a comma!


Using meta viewport


Using meta viewport to optimize rendering on mobile devices

What is the viewport?

Figure 1 - If mobile browsers didn't apply a default viewport, web pages would overfill the screen.

Figure 1 – If mobile browsers didn’t apply a default viewport, web pages would overfill the screen.

Imagine if every web page you opened on your phone or tablet got the same version as your desktop, and was displayed on the small screen of your device. On a phone, that might mean you would see only the top leftmost corner, a tiny 320px by 480px view, and you’d have to scroll around the page to be able to see everything. (See figure 1). Unlike a desktop or laptop, there is no way to resize the browser window to fit the content that you want to see. Thankfully, on mobile devices, almost every modern browser scales and renders the page so that you can more easily see and interact with it, panning and zooming into the areas you’re most interested in.

Figure 2

Figure 2

Most mobile browsers define a default viewport width of 980px CSS pixels, meaning that they lay out the page on a 980px wide area, then scale it down to fit within the width of the screen. (If you’re unfamiliar with CSS pixels, device pixels, device pixels ratios, or the like, check out the Smashing Magazine article Towards a Retina Web. This works great for most desktop sites that don’t take into account mobile devices and were designed for big screens. Sites that were designed to be compatible with narrow screens however are likely to be unnecessarily stretched and scaled. For example, see figure 2 – there is no viewport set, and the image is 1600px wide, that means users need to scroll left to right to see all of the content.

The meta viewport tag allows you to override the browser default value, allowing you to adjust the display and zoom level to best suit your web page.

Using meta viewport

Setting a specific viewport width

To override the default viewport defined by the browser you simply need to add a viewport meta tag in the <head> section of your page:

<meta name="viewport" content="width=320" />
A page with a fixed viewport width.

Figure 3- A page with a fixed viewport width.

Setting the viewport width to 320px, is similar to resizing your laptop browser window to be 320px wide, now the browser will render the page on a canvas that’s 320px wide. If your device is 320px, then you’re all set, the browser doesn’t have to do any scaling and you’re pretty much all set. Obviously not all devices are 320px wide, and your site most likely isn’t 320px wide.

But what happens if you rotate the phone from portrait to landscape, and suddenly the device is now actually 480px wide? If this happens, the browser scales the content up by 50%, so that the 320px width, so that the 320px wide document is stretched to fit in the 480px wide browser window. Unfortunately, when this scaling is applied, less content will be displayed above the fold, and the content may look oversized.

If you’ve designed a site for a fixed width desktop, for example, you know your page is 600px wide, then you can simply add <meta name="viewport" content="width=600" /> to the <head> of your document, which will scale the content to fit within the window. Depending on the density of your content, this may work well, but you’ll want to test it to make sure.

Adding a specific width viewport, is discouraged unless you’re adding it to a legacy site as a stop-gap measure until you can build a more responsive site.

Setting the viewport width to the device-width

A page with width=device-width viewport.

Figure 4 – A page with width=device-width viewport.

Consider the sustainability of a fixed width website and how it would look given the huge variety of mobile web devices, each with a different screen size, it becomes even more of a challenge when those devices are used in landscape mode. For that reason, building your site using a responsive approach and placing it within the viewport without any zooming will help to make your site look great across all of those devices. It doesn’t need to be responsive from phone all the way to desktop, but it should at least flex from a small portrait phone, to a mid-sized mobile tablet in landscape; about 320px to 640px.

When you design your page or web app using a responsive approach, you don’t want the browser to render your responsive content in a viewport that is 980px wide and then scaled down to the tiny screen; instead you want the content to render in the actual viewport size. To do that, you can tell the browser to set the viewport to be the width of the actual device by applying the following meta viewport tag:

<meta name="viewport" content="width=device-width" />

This means the viewport will be proportional to the width of the device’s screen, for example on any portrait iPhone (whether or not it is retina) the width would be 320 CSS pixels, on a landscape iPhone 3 or iPhone 4 it would be 480 CSS pixels, on a portrait Nexus 4 it would be 384 CSS pixels, and on a landscape Nexus 4 it would be 640 CSS pixels

Setting the viewport scale

When you specify a specific value for the viewport width, the browser will automatically determine the appropriate scale factor needed. For example, if you set the width=640 on a device that has a screen width of 320px, the browser will scale the content by 0.5.

In some cases, you may want to specify the scale used by the browser. You can do this by setting initial-scale, minimum-scale and maximum-scale.

<meta name="viewport" content="width=device-width, initial-scale=1" />

Initial scale forces the browser to an initial scale, but still allows the user to pinch-zoom on the content to be able to make things larger or smaller. By using minimum-scale or maximum-scale, you can set a boundary on the amount of scaling the user can do.

You can also prevent zooming by adding user-scalable=no, or setting the minimum-scale and maximum-scale to the same values. This is particularly useful for mobile web applications where it doesn’t make sense to allow the user to zoom or scale content.

<meta name="viewport" content="width=device-width, initial-scale=1, 
  maximum-scale=1, minimum-scale=1" />

Currently the user-scalable property does not work in Chrome for Android (m18).

Setting the viewport height

In addition to setting the viewport width, you can also set the viewport height. While it’s not something that’s used often, it’s good for mobile web applications that may pan horizontally only.

<meta name="viewport" content="height=device-height" />

Practices that are no longer recommended

  • Adding a specific width viewport, is discouraged unless you’re adding it to a legacy site as a stop-gap measure until you can build a more responsive site (you’ll need to replace the 320 with the width of your site):<meta name="viewport" content="width=320" />
  • The viewport property target-densitydpi has been removed from the CSS Device Adaptation specification and should not be used. It has been deprecated in Chrome for Android, and has never been supported in Mobile Safari or Firefox for Android. For more information, see Mozilla Bug 797090 or WebKit bug 88047.

Best practice for using meta viewport

  • Use a comma to delimit different viewport properties. Although semi-colons may work, they do not behave consistently across browsers.
  • For a responsive website, designed with mobile in mind and where the user may want to be able to zoom in to particular areas of content:
    <meta name="viewport" content="width=device-width,
      initial-scale=1" />
  • For a mobile web application where you don’t want to allow zooming of the content:
    <meta name="viewport" content="width=device-width,
      minimum-scale=1, maximum-scale=1" />

The Future

Currently, the only consistent way to specify the viewport for a page is via the meta viewport tag, but the W3C is currently working on a CSS Device Adaptation, that will provide a way to specify the size, zoom factor and orientation of the viewport in CSS using the @viewport rule. As of late 2012, only Opera Mobile 11+ and Internet Explorer 10 provide support for it using a vendor prefix.

Additional Resources


Thinking about the offline web


Over the last few months, I’ve spent a lot of time thinking about how to make it easier for developers to build web applications that work offline, its a tough problem to solve. The web has the features/technology to do it, but I think there are two things preventing us from getting there easily. The first is a perception issue for users, many people think that the web only works when they’re online, no internet, no web. That leads to a bit of a catch-22, users aren’t asking for it, so developers aren’t prioritizing it. The second problem is that it requires a change in the way we build web applications. Instead of building server side web applications, we need to build more client side web applications that use web-based APIs to get what they need.

More than just ‘offline’
But applications that work offline isn’t the only reason to start using these new techniques. There are lots of other scenarios that benefit from the offline experience. For example, the intermittent connection where someone may have a connection for 5 minutes, then lose it for 2 then have it again for 3 minutes. The low bandwidth connection, for people connected maybe by dial-up or 3G modem. It also benefits the person with a great net connection – because any time you load data from the local machine, it’s almost guaranteed to be faster than if it were to come across the network. The performance benefits are pretty significant here!

Reuse the same code for different platforms
If you’re already building native (iOS, Android, Desktop) applications, you probably already have the set of server-side APIs, build your web application to take advantage of those to get the data that it needs. Architect your web application in the same way that you’re building native applications – using the same set of APIs and XMLHTTPRequests! If you’re worried about performance (and everyone should be), you should cache data locally, so that after the first time the app is run, it only needs to get the newest data from the server, and there is some available immediately at start up.

Offline techniques
Building applications that work offline requires two main things, a way to store the applications components (the HTML, JavaScript, CSS, images, and other assets) on the user’s machine, and some way to store data. Solving the first problem is done with the HTML5 feature application cache, which tells the browser to explicitly store the necessary files locally on the user’s computer, and instead of asking for them from the server every time, load them from the cache.

HTML5 offers lots of great ways to cache data locally, localStorage, indexed DB and web SQL. Unfortunately, the only consistently available storage feature today is localStorage, but it’s got a few drawbacks. WebSQL works across most browsers, but it has been deprecated, and could go away at some point. The recommended method, is indexed DB, but it’s not available in all browsers yet, but it’s coming. Check out http://caniuse.com for more info about implementation.

Up next – how do we get users to demand offline?


Introducing Video Player Sample


Have you ever wanted a fun and beautiful way to publish videos on your own site like the new 60 Minutes or RedBull.tv apps from the Chrome Web Store? I’m excited to announce the release of The Video Player Sample! The Video Player Sample is an open source video player web app built using the same architecture as the 60 Minutes and RedBull.tv apps. It can be customized, extended, or just used out of the box and populated with your own content.

How it works

When a user opens the Video Player Sample web app, they can choose to watch a single video or create a playlist of videos/episodes from a list that they have uploaded and populated to the app. The Video Player Sample is configured and information about the videos is stored in JSON files (config.json and data.json respectively), both of which are located in the data directory.

Key features

  • A beautiful video watching experience, including a full screen view
  • Ability to subscribe to shows, watch episodes, create play lists
  • Support for multiple video formats depending on what the user’s browser supports (including WebM, Ogg, MP4, and even a Flash fallback)
  • A Categories page with an overview of the different shows/categories available in the app
  • Notifications of new episodes (when the app is installed via the Chrome Web Store)
  • Built in support for sharing to Google+, Twitter and Facebook
  • To ensure easy customization, all source files, including the Photoshop PSD’s, are included

How it’s built

The Google Video Application is written for the open web platform using HTML and JavaScript, broadly following the MVC (Model View Controller) pattern and structure.

Browser Support

In addition to working as an app that can be installed through the Chrome Web Store, the Video Player Web App has been tested and works in all of the modern browsers.

Try it out

You can see a demo of the video player in action in the demo app, or by Adding it to Chrome through the Chrome Web Store. To learn more about how the app works, check out the documentation.

You can grab the code from Google Code.


Cross Posted at: http://google-opensource.blogspot.com/2012/01/introducing-video-player-sample.html

Go to Top