Kanban & Web Productions: Lessons Learned

Benjamin Sternthal


Kanban has been making in-roads at Mozilla, and this is no small feat considering the size and complexity of the organization. I’d like to think our team has influenced folks, either to adopt Kanban, or to at least think about alternative development methodologies. Below is the history of how Web Productions came to use Kanban and the lessons we learned along the way.

Continue reading …

Firefox Marketplace: June 14th – June 27th

Andy McKay


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

  • Total bugs open: 577
  • Total bugs opened: 244
  • Total bugs closed: 193

Some specific changes of note:

  • Some APIs have been copied to a new namespace for Fireplace because they are unique to Fireplace (bug 875547, bug 875548)
  • Receipt reissue endpoint reserved for when receipt replacement is possible (bug 881788)
  • Reviewer to developer communication dashboard created (bug 879469)
  • Multiple sorting for search results added to the API (bug 867848)
  • Lots and lots of crufty code deleted, which is a big deal to us (bug 881910 and others)
  • Fixes when accessing a pending app (bug 870020)
  • Multiple carrier billing payment fixes in some of the target countries
  • Fixes for Persona changes (bug 884360 and bug 884122)
  • Editing and cancelling reviews work (bug 885297)
  • API now shows created date and number of downloads (bug 867839)
  • Screenshot navigation much smoother (bug 887316)
  • Developed parameter on search API now consistent (bug 886385)
  • Payment setup in the Developer Hub now shows regions for the payments (bug 884443)
  • Cope nicely in the Marketplace with in-app payments that can’t be processed (bug 878216)

The performance on the search API was drastically improved with a few changes. Search performance improvement (lower is better):


Unfortunately, I wasn’t able to attend the “show and tell” meetings recently so there aren’t any updates from there.

Lightning Talk Bonus Round

Michael Kelly

It was raining when the idea first came to me. Deep within the disappointingly well-lit halls of my local coworking spot, I sat in a meditative state as I contemplated the problem of sharing knowledge among the Web Productions team. As my mind drifted in and out of various realities, I came upon a world in which the only television show was the Price is Right. Taking inspiration from the wondrous paradise that this world was, I decided the proper solution was to create a monthly event: Lightning Talk Bonus Round!

Essentially, once a month the Web Productions team gets together to share short 5-15 minute talks on any subject we desire, from programming languages to design principles to mycology. We’re still working out the format and technical details, so there are no recordings available… yet. In the future, we hope to record the event and open it up to the community.

The first Lightning Talk Bonus Round was on June 3rd, 2013. There is a wiki page with links to the notes and details about each of the talks.

Craig Cook – Design Principles

Craig Cook gave a shortened version of a longer talk focused on the basics of Design Principles. He discussed controlling the balance between elements on a page to indicate which elements are more important than others. He also discussed using proximity, repetition, and contrast to help visually distinguish elements and establish the hierarchy of important on a page through visual cues. You can check out his slides on GitHub.

Screen shot 2013-06-18 at 2.53.53 PM

Giorgos Logiotatidis – Django Anonymizer

Next, Giorgos showed us Django Anonymizer, which is a Django app to help you anonymize existing data in the database. As opposed to other methods, such as maintaining fixtures or generating random data, with Django Anonymizer you’d start with a copy of your production data and configure the app to anonymize it, leaving you with data that is anonymous but still looks similar to the data you’d see in production.

This is especially useful in situations where production data may end up with interesting relationships between data that are hard to replicate when generating random data from the start. The Django Anonymizer project is available on PyPI. You can also see Giorgos’s notes in a gist.

Paul McLanahan – virtualenvwrapper and hub

Lastly, Paul talked about two tools that he finds useful during day-to-day development: virtualenvwrapper and hub. virtualenvwrapper is a set of extensions to virtualenv, which creates isolated Python environments for projects that need specific versions of Python or other libraries. The extensions come in the form of commands that help you quickly create, activate, and delete virtual environments. There are also hooks that let you execute certain commands when environments are created, activated, or deleted.

hub is a command-line wrapper for git that has extra commands tailored for working with GitHub. You can clone a repository using just a username and repository name, automatically create a fork on your GitHub account, or even create a pull request for a branch, all directly from the command prompt.

Screen shot 2013-06-18 at 4.45.52 PM

Great Success!

As I gaze over the majestic glory that is the aftermath of Lightning Talk Bonus Round, I realize that we have only just started. My work shall continue, on the first Monday of each month at 10 AM Pacific, in the hopes that someday we will be able to avoid all this knowledge sharing and pool together in a mindspace where thoughts mingle like so many fish in an ocean of web development.

Until then, we shall have to do what we can in meatspace. See you next month!

Firefox Marketplace: May 17th – June 13th

Andy McKay


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

  • Total bugs open: 575
  • Total bugs opened: 384
  • Total bugs closed: 284

Some specific changes of note:

  • Start of moving the API from Django Tastypie over to Django Rest Framework (875540)
  • Privacy policy moved out of the main app object on the API (870557)
  • API added for newsletter signup (874958)
  • Regions added to app detail API (873198)
  • Use the new SIM API to determine the location (867793)
  • Signing in after logging out fixed (869664)
  • Marketplace offline experience much improved (875734)
  • Nicer review form for an app (872840)
  • Google analytics added to Marketplace actions (874076)
  • Feature profile detection added to the validator (862454)
  • The Marketplace now supports OpenSearch (872954)
  • App installation on Linux fixed (876293)
  • Android packaged apps added to the search (878918)


We also do a weekly “show and tell” of things that people have done in the Apps group every week. This is a summary of some of the things that have been shown there.

  • Touch events are now possible in the simulator. Myk demonstrated that click and drag with a mouse is now the same as touch events on the device. Available in the preview version.
  • The simulator “push to device” now works on 64 bit linux because adb has successfully been compiled for that platform.
  • App refresh will automatically detect changes in apps installed into the simulator from the Marketplace. Also command-shift-r refreshes but also clears the application cache.
  • Chris showed off the pending review queue addition to the Marketplace. This allows app developers to see how long they have to wait in the review queue.
  • Amy reported that the review team has onboard five new volunteer reviewers for the Marketplace.
  • Basta showed that the Marketplace JavaScript has decreased in size by using a custom JQuery build. Check out the current size.
  • The Marketplace region is now set from the SIM card.

We were also joined on the Marketplace team by Mathieu Pillard. Welcome to the Marketplace team, Mathieu.

The Crimson Twins

Mike Cooper

Crimson Twins is a project that I started at Mozilla to power two ambient
displays that we mounted on the wall in the Mountain View Mozilla office. We
use it to show dashboards, such as the current status of the sprint or the state of GitHub. We also use it to share useful sites, such as posting a YouTube video that is related to the current conversation. Most of the time that I pay attention to the Twins, is when my coworkers and I post amusing animated GIFs to distract amuse the rest of the office.

Continue reading …

DXR Digests the Firefox Codebase

Erik Rose


How do you reason about a codebase the size of Firefox’s? How do you figure out who calls the function you’re messing with, without losing your context in an endless stream of false-positive-infested greps?

You bust out DXR, Mozilla’s code search and static analysis tool.

DXR begins with the technology that powered the much-missed Google Code Search: inverted trigram indices which turbo-charge a fast regex implementation. It then adds a static analysis engine that rides sidecar with the C++ compiler, noting the location and relationship of code constructs. As a result, you can not only do regex searches that return as fast as you can type, but you can also ask “Who subclasses this?” “Where is this macro defined?” and “Where are all the references to this type?”

Last week saw the first production push of DXR since its major redesign early this year. It now rides on a modern foundation of Flask and WSGI; blocks regressions with a looser-coupled, higher-coverage test harness; and delivers a glut of new features and fixes. Here are some highlights.

Indexing and Search

  • Faster, index-accelerated performance on many kinds of queries
  • Querying for callers and callees
  • Ability to find callers of constructors
  • Recognition of typedefs
  • Links to macro references
  • Links from class declarations to class definitions
  • Better detection of JS symbols
  • Differentiation between a const and a non-const function of the same name
  • Handy-dandy path breadcrumbs so you can tell what file you’re reading and move around in the source tree
  • Sorted folder listings
  • First-class support for mobile and WebKit


  • Several thousand lines less code
  • Slimmer builds which consist of only data, not Python code, making development easier and deployment cleaner
  • Replacement of our ad hoc process pooling implementation with Python 3’s concurrent.futures (knocking off about 200 lines)
  • Flask-powered WSGI instead of old-school CGI
  • Redesigned URLs for MXR parity and future extensibility
  • A Vagrant box to ease the spin-up of new contributors
  • A brand new test harness, exercised by a Vagrant-based Jenkins job

Bug Fixes

  • Trouble-free entry of queries. (Bad JS! Go sit in the corner.)
  • A fix for a crash when doing negated phrase matching
  • Fixes for URL- and HTML-escaping bloopers, including shameful XSSes
  • No more duplicate result lines in some types of queries

What’s Next?

I am pleased to announce that the next release is scheduled for one minute from now. Yes, DXR is now under continuous deployment: if it passes tests, it goes up on the servers, eliminating human bottlenecks and errors and letting us deliver goodies—and get feedback—promptly. A great many UI and capability enhancements are on deck next, along with speedy new server hardware to make queries even snappier.

Want to look under the hood of DXR? Check out https://wiki.mozilla.org/DXR, and join us in #static on irc.mozilla.org. Happy hacking!

Better know a WebDev: Jennifer Fong

Andy McKay

Featuring Jennifer Fong, also known as ednapiranha.


What do you do at Mozilla?

I am on the Developer Ecosystem team and work on the Developer Hub, build reference apps and help developers build apps for the Firefox Marketplace.

Any fun side projects you’re working on?

Yes – let’s see:

  1. Recently created meatspace, a node module that supports decentralized microblogging functionality and subscriptions. Think of it like RSS as JSON feeds packaged with CRUD on posts.
  2. As a result, I made generaltoast, which is a Node/Express app that uses meatspace and Persona to exemplify a web interface for meatspace. You can check out my current microblog – left side are my posts, right side are my subscriptions to other posts.
  3. For a reference app in the Firefox Marketplace, I made generalnotes which is a note-taking app that syncs to the server when the user is online and logged in. Check out the accompanying blog post.
  4. As an attempt to create an interactive fiction game engine, I created generalstore, which allows a user to create a game with text files, images, audio files and CSS.
  5. I am also organizing the remote-friendly NoodleConf, which is an atypical one day conference where speakers talk about whatever they want. Likely relating to technology. Or possibly what they ate for breakfast.

How did you get started in web development or programming?

High school – Watcom Basic and Turing if we really want to be technical about it. Web development was during my later years. Something something PHP something – Aphex Twin may or may not have been playing in the background.

How did you get involved with Mozilla?

I was riding this unicorn across the great Canadian forests and a rainbow appeared in the sky. I followed to the end of the rainbow and saw a job application to join Mozilla. The unicorn touched the application with its horn. The rest is history.

What’s a funny fail or mistake story you can share?

On my first week at Mozilla, I accidentally did a git push -f to master for http://mozillians.org. I felt so bad, but I got over it pretty quickly.

What’s something you’re particularly proud of?

Having some really weird friends. And ideas.

What’s coming up that you’re excited about?

NoodleConf 2013!

Favourite Rob Ford moment?

Firefox Marketplace: May 3rd – May 16th

Andy McKay


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

  • Total bugs open: 552
  • Total bugs opened: 298
  • Total bugs closed: 218

Some specific changes of note:

  • APIs added for payment status and users permissions (868030 and 868252)
  • API to allow the setup of payments for apps (869572)
  • Allow a submission flow that checks app permissions (858306)
  • Enable the German and Polish translations (868888 and 868594)
  • Signing in after logging out fixed (869664)
  • Submitting reviews multiple times fixed (871871)
  • Webfighter demo gained payments (858289)
  • Forced issuers for payments re-enabled (867729)
  • Senior Themes reviewer group created (868053)
  • Move from pyes to pyelasticsearch (857156)
  • Scroll positions preserved between tabs in the marketplace (868249)
  • Stop Marketplace reverting to US after a phone reboot (865132)

The new Marketplace consumer user interface was pushed. The Marketplace is now a packaged app that uses the REST API to populate the app. This was a huge change and makes the site faster and more awesome. To checkout the packaged app see the Fireplace app on github.

The Marketplace was also moved out of Aurora status.

A few UX changes. A single page. Millions of new downloads.

Holly Habstritt Gaal


We recently designed, tested, and released a new version of our our primary download page for Firefox for Desktop. In our tests, we improved the download conversion rate of the top 3 non-Firefox browsers by over 12%! This alone results in millions of additional downloads annually.

Focusing on the entire funnel leading up to a product download and not just the product itself, is as important as the efforts taken to improve retention of a product. This is one of the approaches that the Websites team at Mozilla is taking to improve and support our products.


What is the /new page on Mozilla.org?

This is where the majority of our desktop browser downloads are initiated. For instance, if the user searches for “Firefox”, “Mozilla Firefox”, or “download Firefox” from a desktop browser, the /new URL is the top search result.


What did we change?

Though a relatively simple page, we were able to make number of changes across visual design, interaction, technical improvements and overall user experience that had substantial results. How did we do this?

  1. reduced the number of steps to download
  2. simplified number of actions displayed on page and reduced distractions to funnel user directly to download (ie: no link to Fx for Android or other products displayed)
  3. focus on our product – the last page design did not display visuals that focused on the product, but focused more on Mozilla community.
  4. significantly faster page load time
  5. updated style to our responsive Mozilla style guide
  6. inline page interaction that responds immediately to the user’s request for download, resulting in no page refresh for confirmation and installation instructions.

Old Experience – includes page refresh:

New Experience – inline interaction, no page refresh:

* To experience the inline page interaction yourself, visit the Firefox for Desktop download page.


Design Decisions & Testing

We could infer that the outcome of changes such as updating this page to a consistent style as our other Mozilla.org pages and improving page load time alone would have a positive result. However, some of the other changes were more subjective and required testing and validation before releasing to 100% of our users.

Based on common interaction patterns, what we know about how users respond to pages that “feel” responsive to their actions, as well as minimizing distraction, we were able to make many initial design decisions.  To validate the more subjective changes, such as button placement, button style, and animations, we ran A/B tests using Google Analytics Content Experiments.

​An important part of testing is not just validating our work, but exposing interesting facts about our users and issues that may need further attention. For instance, we learned that large percentage of users downloading Firefox already have Firefox for Desktop. This could mean that the user is not aware that we run silent updates, that they are not aware that their version of Firefox is already up to date, that they wanted a fresh copy of the browser, or a number of other possibilities. This is just one of the interesting things we learned that we are looking into for further improvements.

Given the success of these tests, we were very confident in releasing the new experience to all of our users. Our initial improvements to the /new page and download funnel are just the beginning. We will also continue to test improvement possibilities, such as the style of the download button, to learn more about our users and improve the performance of the download funnel.


A few stats:

Across the top 3 browsers, we saw a 14% download conversion improvement.

Across all browsers and operating systems, we saw an average of a 4% improvement.​

​Considerable improvements to page load time:

  • ​Time to be able to interact: 46% decrease
  • Time to load page content: 71% decrease
  • Time to execute JavaScript: 35% decrease

Next Steps:

Testing download button styles and placement, translate page for non-english languages, add logic and conditional messaging for all platforms to move towards a unified Firefox download page, improve other touch points within the onboarding funnel by using a similar process of testing and validating with real users.


Categories: UX

Avoiding Dependencies

Andy McKay


Guest post on behalf of Matt Basta.

Avoid code duplication and reusing code is always an admirable goal. However, in some occasions, it’s not a bad idea to duplicate a little bit of code in order to make your software better.

An Example

When writing a Node app, accessing a directory listing is fairly simple: the fs.readdir command provides a list of objects in a directory, and a call to fs.stat will tell you whether each object is a directory or a file.

That’s fairly straightforward, but recursing (especially when using callbacks) can require some mental yoga. Each directory needs to keep track of how many subdirectories it expects to receive callbacks for and results need to be aggregated in pieces rather than sequentially.

When I needed a recursive directory listing this past week, I was tempted to use a library: why solve a solved problem? The glob library provides this functionality with very little effort:

Why would you use anything else? Here’s what I saw when I did an npm install glob:

  • glob
    • minimatch
    • lru-cache
  • sigmund
  • grafeful-fs
  • inherits

Simply by adding glob to my project, I’ve added a total of six modules. That’s not unexpected, though, since glob does a whole lot more than I need it to do. In the end, I ended up simply writing my own, and including it in the single file that requires the functionality:

Why are dependencies not good?

First, and most importantly, is the security of those packages. If the SSH keys of the developer of those packages are compromised, an attacker could provide an “updated” version of the library which includes malicious code. At Mozilla, we use internal mirrors of PyPi and NPM to make sure we’re not installing arbitrary modules. Avoiding dependencies helps to avoid requiring a solution.

Second, there’s a performance hit for libraries. If you’re building a one-off fix for a simple problem, using a library increases the overhead of your app’s load and use. If you’re building a web app on Node or Django, you might use an auto-reloader to restart your local server when script files change. In many projects, this takes an imperceptibly small amount of time to reload. As your codebase and dependency list grows, your auto-reloader can take precious seconds to run (we have projects that take almost five seconds to reboot).

Each dependency increases the time it will take to install your application. Zamboni (the code behind addons.mozilla.org and marketplace.firefox.com), for instance, takes 12 minutes to install libraries and dependencies. What starts out as a small number of libraries can very quickly grow out of control and become a serious nuisance. time npm install glob, to reference my earlier example, tells me that glob adds four seconds to my install time. Some simple and unscientific benchmarks from popular node libraries:

  • socket.io: 33s
  • mongoose: 9.5s
  • connect: 5.7s
  • jade: 5.3s
  • express: 4.4s
  • glob: 3.9s

And some from popular Python libraries (run with time pip install <module>):

  • numpy: 110s
  • django: 96s
  • pycrypto: 18s
  • flask: 14s

Third, you’re taking the gamble that the libraries that you depend on don’t have conflicting versions. A great example of this can be illustrated by a web app that I was building: the HTTP requests that I was creating with Python’s requests library didn’t have a .json property, as the docs state. An hour of hair-tearing later, I discovered that another library that I was using had already installed a much older version of requests which lacked the property. Unfortunately, the library wasn’t compatible with the latest version of requests and I had to settle for the old version.

The consequences could have been much worse, and this is a not-well-solved problem (for the Python community, at least).

Last, if your project is used as a library, including dependencies decreases the re-usability of your code. If your code uses a third-party library when it could have taken advantage of some slightly-gnarly standard library tools, all of the above reasons make it that much more difficult for a developer to justify using your tool.

Now hold on just a minute.

Does this mean you should never use an external library? Not at all! You should use libraries whenever it’s appropriate. Sometimes the effort required to perform a task correctly and thoroughly (or at all) is simply too much work to do on your own. OAuth? You’ll probably want a library. Database work or ORM? Use a library. But what if you need to serve a single static HTML file over HTTP? You can probably use Node’s http or Python’s SimpleHTTPServer without too much heartache.

Sometimes it’s just irresponsible to write code yourself: would you trust a developer’s one-off method or a mature ORM’s SQL sanitization code? What about code to generate secure random numbers for encrypting sensitive data? Or code that protects against XSS attacks? There are a lot of instances where it’s in your users’ best interest to use a trusted solution rather than your own solution.

A double-edged sword.

Another reason for choosing libraries is the community: if there are bug fixes to a third-party library, dependents can relatively easily update to the latest version of the library and take advantage of the improvements immediately.

That can be a good thing and a bad thing, though. Libraries without a community around them can contain bugs that don’t get patched in a timely manner. Fixes may be difficult or impossible to upstream.


  1. If you can easily get by without a dependency, you don’t need the dependency.
  2. If you’re building a library, you should avoid dependencies.
  3. Don’t avoid dependencies if it means potentially putting your users at risk.