The Kinda Offline Web

Matthew Riley MacPherson

1

Offline technology is mature enough to use, but do most web developers know how?

The phrase “web app” has traditionally meant something like Basecamp — an app accessed at a URL. But many traditional web apps are online, slower that locally-hosted apps with no latency, and bound to a browser. At Mozilla, we’re trying to change all of this with FirefoxOS and Open Web Apps. One of the biggest changes to what we call a web app can be encompassed in one word: offline.

A few months ago I started work on Face Value, an open web app that deals with a currency’s denominations in a saner way for most travellers. I knew the app would need to work offline; most users would use the app on their phone, often in a foreign country without a data plan.

I know a lot about the localStorage API and even some things about Appcache, but I hadn’t ever made a truly offline web app before Face Value. What’s worse, I didn’t know about some of the really common gotchas one runs into when going from building web apps that rely on a net connection to ones that work offline without issues. My first few attempts were quite buggy, but in the end I have something that I’m quite proud with and trust to take with me–even when I’m without precious, precious data on my phone.

Ingredients

So just what does one need in order to make a web app function offline? Turns out the list isn’t too long:

  • Appcache is basically mandatory
  • localStorage allows you to store user data on the client
  • indexedDB lets you store huge files, but we’ll save talking about it for an upcoming post

“Wait, that’s it?” you might be thinking. It’s not a lot of tech that goes into writing offline apps. But the amount of edge cases, misconceptions, and gotchas are much bigger.

localStorage

Storing user data locally, it turns out, is actually the most straightforward task of the bunch. localStorage’s API is obscenely simple: it’s a key-value storage system accessible like any other JavaScript object; window.localStorage.myName = 'Matt' will set the key myName and window.localStorage.myName will predictably return 'Matt'.

The two biggest gotchas to localStorage are:

i. localStorage offers a finite amount of storage.

It’s safe to assume you have at least 2.5MB to work with, which should be more than enough to store app data, serialized Backbone objects, and user settings. Browsers vary in the size they give out for localStorage and how they deal with it, but in Chrome, Firefox, and Safari you’ll have at least 5MB to work with. So don’t try to store large binary files or HUGE chunks of data in localStorage. For most apps though, this is more than enough space.

ii. localStorage should’ve be called “stringStorage”.

localStorage only stores strings. If you attempt to save anything that isn’t a string to localStorage: it won’t work and will fail silently. In order to save other data to localStorage you’ll need to convert it to data that can be represented inside a string. Effectively, this means running JSON.stringify() on anything you save to localStorage (conversely, when getting data from localStorage, just run JSON.parse() on any data you’ve saved this way).

Of course, if you’re storing complicated data (like Backbone models), you’ll want to look into something like the localStorage sync backend Face Value uses.

The main thing to remember is that you’ll likely want to abstract getting/setting data in localStorage to handle the JSON conversion; here’s the code that does it in Face Value.

Appcache (is a Four Letter Word)

Appcache is the technology that allows you to explicitly instruct the browser which assets on your (or someone else’s) server to cache locally for your app to request. It’s powered by a very simple “appcache manifest”, which looks like this. It powers facevalueapp.com and ensures it works even once your computer or phone is offline. It’s an awesome idea, but it’s got some rough edges that you really need to be aware of before attempting to leverage it. I think that had someone warned me about these pitfalls before I started building Face Value I’d have been much better off (and spent less time cursing Appcache).

It’s Oh So Quiet

If you’re used to using Firebug or Chrome/Firefox/Safari Developer Tools, you’ll notice there still aren’t amazing tools for inspecting stuff in Appcache. Actually, Appcache still doesn’t have a very mature API and its support in browsers is still early. Hopefully this is made better in the future, but the two things you need to know are:

  1. Every file in your Appcache Manifest must be accessible (no 404s).
  2. If a single file in your manifest isn’t available your manifest isn’t valid and all cached data is invalidated.

This might seem harsh, but the trick is simply to remember to make sure all files in your manifest exist. In a future post I’ll try to show you some events you can attach handlers to so you can check for Appcache errors. For now, just remember these rules.

Reload!

It might seem unintuitive that the cached version of your page isn’t used until after all files in the manifest are loaded and the URL is requested again. But because your Appcache isn’t considered ready until everything in it is downloaded, this makes sense. Effectively, you need to do a window.location.reload() once all resources are available. This is especially important if you want your app to work offline as soon as all files are cached; if you’re marketing your app to iOS users who may well next access your app without data, they’ll be treated to an error message claiming an Internet connection is required. Refreshing the page and forcing a load from Appcache fixes this problem.

Under Your Thumb

Appcache manifests contain three sections: CACHE, NETWORK, and FALLBACK. Learn to love all three, and remember that because a single error will render your cache invalid, it’s important not to put any asset you don’t directly control and serve in your CACHE section. For instance: you’re using Google Web Fonts and want to cache your font. Fair enough, but because you don’t control that asset it’s worth placing it in the FALLBACK section where you can specify a different, local resource for it. Alternatively, you can pull in external resources (like content from a CDN) and put it in the CACHE section.

Just be careful about including foreign assets in your Appcache manifest — you’re effectively handing control of your cache validity to someone else then.

Conditional Network Access

It’s a common scenario to have an app that functions perfectly offline, but does make occasional network requests to do things like update data. Face Value is an excellent example of this: all currency and denomination is stored offline, but currency worth (accessed via Yahoo’s Finance API) and currency/denomination data (accessed via Face Value’s server) are updated once a day. More accurately, if it’s been more than twenty four hours since you last opened the app, Face Value makes a network request to update its dataset before firing a callback that launches the app. Once the data is loaded, Face Value continues loading as normal; if it’s been less than twenty four hours since you last updated, the page is immediately rendered without any network requests.

Unfortunately, in earlier versions of the app, I didn’t anticipate this network request failing because I usually tested the app’s offline capability immediately after I launched a fresh version of the app, meaning it was mere minutes since I last obtained this currency data. So my app worked fine in terms of localStorage and Appcache, but that network request failing just wasn’t something I encountered in my manual testing!

The Kinda Offline Web

It’s important to think that any network request can fail (even on first load) when building offline web apps. My bug with conditional network access was easily fixed, but it’s not the kind of thing web developers typically think of; even when we think offline, we’re thinking a client-side game or token web app that never needs network access again.

The reality is that many apps need network access some of the time, but you have to be prepared for the reality of mobile apps: when you need network access it, you might not have it.


These were the particular gotchas I experienced during my time getting Face Value to work offline.

I’m currently working on a podcasts app for FirefoxOS and Firefox Desktop that stores large blobs of binary data. Because of Appcache’s fragile nature and localStorage’s limited storage, I used IndexedDB to store podcast files. I’ll talk about my experiences with IndexedDB (and the wrapper around its API I’m working on) in an upcoming post.

Switching to pip for Python deployments

Andy McKay

2

For the last year or so addons.mozilla.org and marketplace.firefox.com have deployed primarily by pulling the entire project out of github. Required libraries were placed in a git submodule called vendor. Vendor was then a git submodule of our project, meaning we had recursive submodules. At deployment time we recursively pulled all the modules from github to our master server.

This created a few issues. The recursive pull from github was quite slow as we pulled down an awful lot of code. To update something in vendor was quite a tortuous path of updates that generated quite a few expletives from most developers the first few times they tried it. Scripts were written to make that made it easier, but that was just addressing the symptom. Multiple commits appeared in zamboni that had accidental vendor changes in the submodule and more expletives were uttered.

Because everything ended up underneath the main project anything that recursively searched directories took longer. Some git commands, greps, test runs etc took longer and longer as the vendor library grew.

Finally, building packages and using pypi and the existing community infrastructure is a good thing. It means that our code is as close to as normal as possible and our libraries are more likely to be reused if we package them properly from the start.

How we build

We don’t want any surprises about what pip is installing on our server. Often the setup.py script installs dependencies. To prevent that we invoke pip with the --no-deps flag. All dependencies have to be manually specified in the requirements files.

For each package we pin to the specific version, for example Django==1.4.3. This is a little faster since pip doesn’t have to find the relevant version. It means we have to manually update, but it ensures we don’t get a version we didn’t expect. Updates are so much simpler and easier to read in source control (for example).

Unfortunately not everything is a package. We have a few packages that pull directly from github as eggs (as of writing we have 80 python packages and 20 eggs from github). For those we set --exists-action=w to ensure that if those change the deployment continues smoothly.

Security

There are more security issues with taking a package from pypi and installing it on the production server than there is with pulling from github. We wanted to be sure that we were being as safe as possible.

So we set up a server to store local copies of our packages. It is a simple HTTP server that serves from the file system and developers have to scp packages over to it. The deployment pulls from that instead of from pypi, ensuring that we’ve got accountability and traceability about what packages are going to our production servers.

Before developers can get access to upload packages, they have to read and sign off a policy for uploading packages.

Results

The deployments are now slower because we delete the existing virtualenv and reinstall the packages from scratch each deployment. This was a temporary measure to cope with the large number of package changes over first few deployments. This part of the deployment takes about 2 minutes, which is the slowest part of the deployment. Once we stop deleting the virtualenv that should improve.

The vendor submodule still exists to look after legacy code that hasn’t been put into packages or is unlikely ever to do so. It also contains one JavaScript library.

The number of expletives issued by developers during library bumps has dropped and the number of commits with random vendor changes has vanished. Although there have been a few expletives uttered at packages. Updates are faster, git and other command line tools are faster. Overall, life is a whole lot better.

We’ve now got at least four projects using and deploying with pip and we won’t be going back. Hopefully more Mozilla web sites will now also be able to deploy with pip.

Thanks to help from Jason, Jeremy and Guillaume for making this happen.

Firefox Marketplace: Jan 4th – 10th

Andy McKay

This is a weekly post focusing on the status of the Firefox Marketplace.

  • Total bugs open: 424
  • Total bugs opened last week: 50
  • Total bugs closed last week: 40

Some specific changes of note.

  • PIN entry for payments will be locked out after enough failures and then unlocked again (bug 827580).
  • Mixed content warnings squashed on B2G phones (bug 823174).
  • Allow web, privileged or certified apps to be uploaded (bug 826889).
  • Much improved bank details submission for payments.
  • Fixed screenshot thumbnail upon swiping (bug 822288).
  • Support for unverified Persona accounts (bug 828068).
  • Fixed non-ascii slugs for reviews (bug 813730).

Most of the payments work for the Marketplace is now taking place in two external repositories solitude and webpay. If you are looking to make some contributions to the Marketplace, those might be a good place to start.

Firefox Marketplace: Dec 27th – Jan 3th

Andy McKay

This is a weekly post focusing on the status of the Firefox Marketplace.

  • Total bugs open: 425
  • Total bugs opened last week: 45
  • Total bugs closed last week: 24

Some specific changes of note.

  • The app validator for the Marketplace is now available without login (bug 820614).
  • Bad permissions in the app manifest are now caught in the app validator and will raise an error (bug 823691).
  • Website statistics converted to using Google Analytics, not Webtrends. (bug 821923)
  • Updated feedback on apps in the Marketplace (bug 811354).
  • ETags added on the packaged apps created so that apps can be installed. (bug 825209)
  • Lots of payment updates, including integration between the Marketplace and Bango (multiple bugs).

As part of our effort to split zamboni into smaller parts, Monolith was created as a service to hold stats. This will allow us to split the code and data out of zamboni.

Mozilla Webdev’s Beer and Tell: November 16, 2012

James Long

Every month Mozilla Webdevs get together and give lightning talks showing cool things they’ve been hacking on for work or for pleasure. The November 2012 Beer and Tell was enjoyed by all. Now that Thanksgiving is over and I’m overly stuffed, it’s time to blog it!

A video recording is available at the end of this post, so feel free to skip down to it.

MagmaForce

Michael Kelly (mkelly) showed off MagmaForce, a very well-executed and addicting game he made at a hackathon. You must save yourself from the impending mine collapse by grabbing magma balls, shooting them somewhere else, and matching up colors so that they disappear. There are even combos and special balls which dissolve huge amounts of balls in one shot. Be careful opening this game, you might spend a lot of time playing it!

The code is available on github, of course, if you want to take a peek at how it works.

AuroraOS Concept Demo

Scott Michaud, a potential contributor, showed us a proof of concept OS for tablet devices based on web technologies. You can view in here. He calls it “AuroraOS” due to the main screen showing a cool dynamic WebGL-rendered aurora in the background. Note that this is completely different from FirefoxOS and is simply a proof of concept, not an ongoing project within Mozilla.

Pressing “down” brings up a list of tabs, which represent multiple programs, and a button with a menu that allows you to change settings, view history, and perform other system-level tasks. There’s also a neat keyboard that allows you to use your thumb to pull up suggestions of letters, depending on what you’ve already typed. It doesn’t auto-complete whole words, but it simply suggests the next letter according to a probability of what you already typed and what you might want to type.

Scott’s OS contains a few other interactions heavily optimized for touch devices, and a lot of work and thought has gone into it. Impressive — thanks for showing it Scott!

Crimson Twins

Mike Cooper (mythmon) solved our dilemma of what to do with 2 wall-mounted TVs in the Mozilla office. He wrote a node app that connects to IRC, responds to messages containing URLs, and opens them in a browser connected to the app. The browser can display several things in a grid, or one thing can simply take up the whole screen. URLs can be anything from images and videos to real websites. It uses now.js to stream content to the browser. Very cool!

It also features a kill switch, so if you tell the bot “ohshit” it will clear the content in the browser. Additionally, it curates URLs from noodletalk to attempt to keep things clean (we love you ednapiranha!).

Coming to a webdev wall near you!

3d Graphics Experiments

I (jlongster) showed some demos of a 3d graphics engine called Shade that I’ve been working on (my blog post about it is here). It’s a hacky project driven by requirements for a game I’ve been working on for github’s game off.

Shade features a basic 3d scene graph, and a renderer that optimally sorts it and renders it. It attempts to minimize context switches which are expensive in WebGL. It also features the basic needs for a 3d scene: a camera, a mesh loader (.obj format), shader loading and compiling, and various functions for managing the scene. The goal is to be simply and still relatively low-level, while removing most of the grunt work when working with WebGL.

Essentially, it’s a fun project for me to learn WebGL, and might help others learn it too! Obligatory screenshot:

I’m using this to build a first person shooter for the web. Since the Beer and Tell, I’ve also implemented multiplayer networking and a bunch of other stuff! View my blog for more details about it.

leeroy-rerun

Chris Lonnen (lonnen) followed up a previous Beer and Tell demo about leeroy with a utility he wrote called leeroy-rerun. For some context, leeroy is a project that integrates jenkins with github pull requests, which is awesome. It automatically runs tests when a PR is created and posts the results on the PR. However, you can’t rerun tests without making code changes, which makes it difficult if you want to change something else in the environment, like a database.

leeroy-rerun is a python script that lets you rerun tests on PRs without any code changes. Simply run the script from the command line with a URL to the pull requests, and magic stuff happens for you, including a brand new test result. You should use this if you use github’s pull requests!

And that’s it! Thanks for tuning in!

Video

Switching to django-compressor in Playdoh

Schalk Neethling

3

Around six months ago the Mozilla Playdoh project, a web application template based on Django, switched from using jingo-minify to using django-compressor for all things ‘combinable’ and ‘minifiyable’. Along with this we started using the staticfiles app i.e. django.contrib.staticfiles.

Both of these have been positive moves and while funfactory does most of the heavy lifting to upgrade your project successfully, or setting it up if it’s a recent clone, to use the above, there are still some changes you need to be aware of and make manually. These are the items I will then cover in this post.

NOTE: I here assume that you have already created and setup a basic Playdoh project using the Playdoh documentation here.

Referencing Static Files

The first thing we need to look at is how static files are references when using the new libraries. If you have been using jingo-minify you will be used to creating bundles in settings/base.py and then referencing those bundles in your template, for example:

Now with django-compressor there is nothing to do in your settings and you would include your assets as follows:

Now in late January of this year (2012) the project layout of Playdoh projects also changed in the sense that is no more apps nor media directory and instead, there is a ‘projectname’ folder. The great thing about this combined with the above two is that it is now possible to keep the assets needed for your app right there with your templates, views etc.

So, what does a typical project layout look like?

Well after funfactory has created your app you will have a structure as follows (looking only at the folder related to you project):

projectname
-- base
---- templates
------ .gitignore
------ 404.html
------ 500.html
------ example_base.html
---- __init__.py
---- models.py
-- examples
---- static
------ examples
-------- css
-------- js
---- templates
------ examples
-------- mobile
---------- ...
-------- bleach.html
-------- home.html
---- __init__.py
---- models.py
---- urls.py
---- views.py
-- locale
---- ...
-- settings
---- ...
__init__.py
urls.py

Whoah, that is a lot but, for the purpose of this post we are only interested in the base and examples folder. Going from the top, go ahead and create a folder called static inside the base folder and in this folder you can then store all of your core static assets such as your images, CSS/LESS and JS etc.

Next you can either create a new folder at the root of your project folder that matches your projectname and remove the examples folder or, rename the examples folder to match your project’s name (this is what is assumed here, so most things will already be there but follow along) and remove anything you will not need. Inside this folder move into the static folder and again rename examples to your project’s name and do the same inside the templates folder. You should end up with something like:

-- base
---- static
------ css
------ img
------ js
---- templates
------ .gitignore
------ 404.html
------ 500.html
------ base.html
---- __init__.py
---- models.py
-- projectname
---- static
------ projectname
-------- css
-------- js
---- templates
------ projectname
-------- home.html
---- __init__.py
---- models.py
---- urls.py
---- views.py

Before we can start coding, we need to add something to our urls file to make development smoother i.e. you do not need to run the collectstatic command every time you add something new or make a change to an existing file. Inside the root folder of your project open the urls.py folder and add the following (This might already be present so double check before adding):

Now we are ready to code our project and use our static assets. Inside your base folder open up the base.html (if it is still called example_base.html, rename it) folder. Inside the head section of you page add the following to link your main CSS:

As you can see here we are using the static function inside the href of the link tag to point to the file we want to include, we also wrap this up in a site_css block, that will come in handy in a minute, as well as using compress css. The site_css block gives us a hook that we can later use to override what is in base or, add something additional. The compress css will ensure that what is inside it will be minified and potentially preprocessed if you use, for example LESS (as is the case in these examples).

NOTE: If you are using LESS you need to ensure that you have Node.js and the lessc preprocessor installed and that it is in your PATH. For more on this see the LESS website’s server side section. Also, django-compressor has built in support for LESS by default and will as such recognize the use of text/less as the value for the type attribute on the link tag.

Next, move into your projectname/templates/projectname folder and open up index.html

As you can see from the above we here use the site_css tag from before and then call super() which will ensure the file(s) defined in the template we are extending is included as well as the new file(s) we are adding for this specific template. The one difference you will notice is that inside the index.html file, instead of using css/ourfile.less, we are prefixing it with projectname/css/ourfile.less, this is to inform Playdoh that you want to load the file from the static folder of your projectname folder and not base.

The same then also goes for including images as well as JavaScript but, with JavaScript there is a slight difference:

The main difference being creating a block called site_js and then calling compress js inside your block. Inside your template extending base, the usage is then the same as before with this one change.

This should then get you up and running quickly and easily using django-compressor, the staticfiles app and the new project layout of Playdoh. If there is something I missed or you have any additional comments or questions, please feel free to add them in the comments.

Things I learned from looking at graphs

Andy McKay

We use Graphite to see how the Firefox Marketplace and Add-ons sites are doing. But the sheer volume of traffic to Add-ons always gives some interesting graphs.

A while back we were switching between different clusters for add-on version check as the hardware behind it changed. As we switched clusters, we also switched from a hot cache to a cold cache. This resulted in a spike in traffic:

That’s almost 45,000 requests per second coming into version check and being processed by Python and MySQL. With hardly a blip on the hardware loads, we processed that quickly. We can see the affect as the cache picked up the slack, it falls down to the usual 8,000 requests per second. Crazy traffic.

We get a large number of requests to version check for a small number of add-ons. Like Adblock Plus which, as of writing this post, has over 15 million users. That’s pretty awesome.

Looking at the traffic to Add-ons site (excluding version checks), traffic is very consistent depending upon the time of day.

So when are those times? Here’s a graph of today’s traffic that I’ve annotated.

Our low point is as India wakes up. It goes up as Europe starts to wake up and then the east coast of the US. It hits its peak at about 11am on the east coast and then as Europe and the east coast goes of line traffic starts to fall.

There’s no real surprise there and data is backed up by looking at our internal metrics that show after the United States, the biggest traffic for Add-ons comes from Germany, Russia, France in that order. But it’s always nice to be reminded of the global reach of Mozilla.

Mozilla Webdev’s Beer and Tell: October 19, 2012

mcooper

Every month Mozilla Webdevs gather around the video conference screen to hold a series of lightning talks and demos of cool things we have worked on in the last month. The October 2012 Beer and Tell has happened, so lets blog it!

We have lots of cool projects in store for you. As our local fez wearing Potch put it:

This week on Beer And Tell: lonnen keeps pull requests stable but not his laptop, groovecoder teaches us all to do the Electric Slide together, jlongster reinvents the wheel and somehow makes it rounder, ubernostrum goes looking for trouble, peterbe takes it offline, andym clocks you in the nose, brianloveswords cares about the environment, wenzel spies on his Pis, davida gives us all mad ups, and jsocol shows us all what he can C.

Continue reading for a summary of the presentations, or jump to the bottom and watch the recording of our video call yourself and see the demos for yourself.
Continue reading …

Pre-Integration Testing

Lonnen

This is a cross-post of an article on Lonnen’s blog X⊕R.

Reviewing a pull request to Socorro involves a series of filtering steps up front before the reviewer even considers the substance of the proposed change — does it violate the style guide? Does it pass our test suite? Most of these are checked by our CI server runs after an SCM change. It’s always embarrassing when you’ve thoroughly reviewed and merged a commit to find that it broke the build; and it effectively blocks the rest of the team from working while you sort out the failure.

But the preliminary steps get tedious, and that green merge button is so easy to click, and even when the reviewers do everything by the book differences in our developer environments and the servers we build and deploy from can lead to unexpected breakage.

If we run tests after code is integrated to master, why can’t we run them before?

Travis-CI does this, and it’s awesome. I’ve set up libraries to run there and pre-integration testing has been immediately useful. Especially when new contributors drop by with patches. Unfortunately, Socorro’s build process is a little more complicated and Jenkins is our CI of choice. Rather than maintain two separate build systems, I went looking for ways to get Travis-CI style testing from Jenkins. It needed to post the status of the build job back to the pull request, run automatically, and appropriately handle pull requests from other forks of the repo.

Introducing Leeroy

I found Leeroy, a small Flask app that listens to GitHub pull request events, parses them, and triggers a parameterized Jenkins build to test proposed changes before your merge them. As the job runs, Leeroy keeps the GitHub status API updated so the curious can follow along.

The project readme thoroughly covers installation. Leeroy requires accounts with access to your Jenkins server and your GitHub repo. You have to install a few plug-ins from the Jenkins UI, and then create a parameterized Jenkins job. I was able to clone our existing job and make a few tweaks to save space. Leeroy happily runs on a single Heroku dyno if you specify a port in your procfile (leeroy -p $PORT) and specify your own settings file with a heroku config variable. Once it’s running, newly opened or updated pull requests will have some additional UI to show their status.

a screenshot of a running job

No developer is prevented from merging, but the UI does encourage smart behaviors by default. While a job is running or after it fails, the merge button is still present but no longer an inviting green. Instead it comes with a cautionary message.

a screenshot of a failed job

A status dot appears next to each commit that was run as a build. I’ve configured ours to build only the tip of the branch when multiple commits are pushed. The dot is a permalink to the Jenkins job testing that commit, and on hover it displays the job number and status. As a feature develops in Socorro it will have multiple builds in the history to look back on, which can be helpful for the reviewer.

a screenshot of a running job

On build success, there’s extra green on the screen confirming this change passed the CI tests. At this point, it’s ready for a person to come along and examine the substance of the change, knowing that Leeroy/Jenkins has caught any style guide violations and obviously broken tests.

How’s that new robot working out?

Our LeeroyBot is only set up for Socorro components, but it is nearing 150 build jobs for its first week. About one-third of those were failures. At 25 minutes of time to discover each failure manually, the back-of-the-envelope has LeeroyBot saving our team about 20 hours, or 2.5 work days this week.

Furthermore, it’s actually changed the way we review and develop code. Nobody is trying to be a wetware pep8, or checking every line for trailing spaces; the focus is shifted away from nits and onto the implementation. Quick fixes are much quicker, and feature branches have become more discussion like.

It’s not a perfect system. Builds break on external dependencies sometimes. Network traffic occasionally times out. Updates to master don’t cause existing pull requests to be re-run, so two commits that green light independently may have a poor interaction. All of these could be helped by manually triggering a build, but for the time being you need to modify the pull request commits to trigger a new build. I’ve filed the issue 9 to figure out a means of resolving this.

On balance, LeeroyBot has had an overwhelmingly positive response from the other devs, and, having survived his first week, will see only expanded use in the future. Many thanks are due to Joe Shaw and Charles-Axel Dein for their excellent work on Leeroy. I recommend it to anyone using Jenkins and GitHub in their day-to-day development.

Apps are Boring; Games are Fun

Matthew Riley MacPherson

A few weeks ago I headed down to Porto Alegre to help out with a Mozilla hack day after BrazilJS. I was around at the BrazilJS event as well, but I only fielded the odd question as most attendees were off at the awesome talks (it was a single-track conference — my favourite kind). As a result, I didn’t exactly know what to expect from the hack day, seeing as it was to be a mix of BrazilJS attendees and folks who heard through the grapevine there’d be a day of hacking. It was also my first time in Porto Alegre (and in Brazil, for that matter) so I had nearly no idea what to expect of the coding scene there.

Well hot damn I was impressed.

I was sent to Brazil pretty last-minute, so speaking at BrazilJS wasn’t possible. But I did get to give a brief talk after Brendan Eich showed off BananaBread — which was basically the perfect segue ever.

Building More Exciting Apps

I spoke for what I remember to be about twenty-five minutes about building open web apps with Mozilla’s kick-ass app templates (mortar, WebGameStub, and sutthisan). I focused specifically on ditching the tired idea of making your first app a grocery list or Twitter client; I argued instead that game programming in HTML5 and JavaScript — especially 2D programming — was within the grasp of many more web developers than it was even a few years ago.

Mozilla’s WebGameStub makes this especially easy; it’s a simple game loop plus a <canvas> tag that lets a developer get their own 2D game engine started with no extra boilerplate. It even includes a demo game that you can use to bootstrap your own game (which is how yours truly got started). Another Mozilla web developer, Fred Wenzel, was able to build a snake clone and ship it to the Mozilla Marketplace in an afternoon. I added iOS support and touch events easily. Turns out: this stuff isn’t hard at all!

So after I stood in front of a decent-sized audience and spoke in weird English for half an hour to a Portuguese audience, we got hacking.

Photo of Porto Alegre hack day audience

A shot of some of the hack day attendees at my talk.

Of Woes and Wifi

Hundreds — sometimes even dozens — of people storming your wifi just doesn’t work. We got stuck with pretty slow connections for everyone, which meant I was fielding a lot of questions and folks were having trouble getting access to GitHub and the awesome Mozilla Developer Network. I was worried that between my very English help and the crummy wifi it wouldn’t be a very productive hack day. With about three, maybe not quite four hours of hacking behind us, we announced that it was demo time.

Unexpected Turnaround

I was running around the whole day, helping people with JavaScript questions, API nonsense, and whatever else, that I barely got to really see what they were working on. Other groups were a bit secretive of it. But what they turned out from a few hours was totally awesome. My two favourites from the hack day were:

There was even a modified version of the demo game included in WebGameStub to be a somewhat Sisyphean version of the original. I got a bit of a kick out of that one.

Make Bacon game screenshot

Even vegans should find this funny.

Make Something Awesome

I did a short demo of the aforementioned Serpent and our own flux-game — the result was an afternoon of games including more than just the highlights I picked out. The takeaway for me was validation of what I was saying to all the hackers in Porto Alegre: you can building something fun, something unique, and something genuinely cool with the APIs and tools provided by the web.

So stop building to-do apps and make the web a more exciting place!