Can you detect WebDriver sessions from inside a web page?

When you install a fresh copy of Firefox and run it for the first time, it opens a few tabs. For example, since August 2017, new installs of Firefox open the Firefox Privacy Notice in one tab on first run. The actual content can vary between versions and across platforms.

Last year we noticed some unusual traffic patterns on these pages: Lots of visitors came from countries like Finland that generally make up a tiny fraction of our traffic; many were on linux; and many came from ISPs named after the world’s largest data center operators.

If you’ve done much web engineering, you’re probably running some variation of this heuristic in your mind:

  1. Do I know anyone who uses a remote linux box in a data center for normal web browsing? (Maybe.)
  2. Do I know enough people who do that to make any kind of blip in the large volume of traffic that visits (Nope.)
  3. What else might explain lots of linux boxes installing Firefox and running it? (Testing automation, perhaps?)
  4. What testing automation tools drive browsers? (Selenium WebDriver!)

At this point we’re back to the title of this piece: Can you detect WebDriver sessions from inside a web page? Because that sure would be interesting, right? If your website gets a lot of testing bot traffic, and you could detect it, then you would know more about your site’s traffic, for example. Or maybe you could do something more interesting with bot traffic than just show it whatever content it requested. Etc.

Lucky for us, we’re not the first to ask this question. Lots of people have asked it before. The best answers I found in my own searches are over on StackOverflow in response to “Can a website detect when you are using selenium with chromedriver?” and “Selenium WebDriver is detectable“. Answers to those questions suggest an entire suite of client-side tests we could run to discover if WebDriver is driving a browser. For example, one respondent says that the html tag of the document will include an attribute added by WebDriver (or by geckodriver, the Firefox proxy for WebDriver). Another suggests testing the presence of navigator.webdriver. And so on.

Other responses to the question say it’s impossible. Their line of reasoning goes like this: WebDriver is running a browser for the purposes of simulating real browsing activity, and a good simulation should be indistinguishable from the authentic thing, so of course WebDriver should be undetectable.

One interesting feature of these conversations is they appear to include lots of people who want to be sure their bot activity won’t be detected by whatever website they point it at. For example, one of the most detailed responses explains how the respondent circumvented detection on a site that sells concert tickets. “It worked,” they say. It would appear that my own use case is rather tame, in comparison.


Well, there was enough controversy around the topic to inspire a bit of coding on my part. I built a trivial little tool that runs all the tests I could find; if any of the tests can discern WebDriver at the controls, my WebDriver test would pass.

Digression: While the code itself is trivial, getting it to that state was definitely not. I code so rarely these days that I have to reestablish my development environment each time. That means I end up with the latest versions of e.g. node.js and the node bindings for WebDriver and the Jasmine testing framework. And that means I run into all manner of incompatibility among libraries and between documented/example usage and actual usage. It feels like exploring a new continent full of undiscovered affordances.

Nevertheless, I eventually banged out some code that appears to run. And then I ran it.

So, can you detect WebDriver sessions from inside a web page?

Before I get to that I want to point out that I have the great luck to work at an amazing company. I get to rub shoulders (or whatever the IRC equivalent of that is) with people who help shape the future of our most critical technologies (by way of specifications and implementations) and help determine technology’s role in society (by way of advocacy, education and straight-up lawsuits against the federal government, when necessary), and that makes me proud.

Some of the people I work with contribute a lot to automated testing tools like WebDriver. They are very patient when someone like me bungles into their IRC channel to ask this sort of thing. So when my tests completely failed to ascertain whether a bot was at the wheel of my browser, I reached out to those folks and asked: Should I be able to detect WebDriver sessions?

And they said, “Probably not.” Which was my experience, too.

A patch is in the works to expose an attribute on navigator, such that navigator.webdriver !== false, when geckodriver is driving, and when the person who launched geckodriver has not made any code changes to obscure their ticket-scalping side business.

Also, several companies market tools designed to “fingerprint” a browser, because doing so creates all sorts of opportunity to trade the identity of the browser (and the person running it) for profit. (It’s like silver mining, except the miners ride Uber instead of mules and the silver is extracted from your soul!) Of course such technology might also be used to thwart networks of bots, since bots can theoretically be identified in the same manner.

Meanwhile, if you just want to add some simple JavaScript to your page so you can innocently ask a browser whether its driver is a robot, you’re out of luck. For now.



Can you detect WebDriver sessions from inside a web page?

You should learn to code.

A proliferation of online courses promising to teach you how to write computer code have attracted some big celebrity names recently, and some celebrities have even launched things. But even if you’re not a billionaire mayor, you probably should learn some coding skills. Below I offer six good reasons to try.

First, let’s be clear about terminology:

  • For the purpose of this article, I mean the same thing when I say “coder”, “developer”, “hacker”, or “programmer”.
  • When I say “code”, “develop”, “hack” or “program”, I really just mean, “create coded instructions that a computer can interpret to produce some result.” Computers are machines that implement logical instructions. Coders write the instructions in code.
  • When I say “coders write the instructions,” I mean they use a keyboard, not a mouse. Coders don’t drag & drop code. Coders do write drag & drop code, though.

Now that we’re talking about the same thing, here are six reasons you should learn to code.

REASON 1: If you learn to code, you will be a better communicator in the future.

Some autumn day in 2020, you will find yourself feeling a little chilly despite the silver bodysuit you’re wearing. So you will say something out loud like, “Hey house, please turn up the heat three degrees.” Then a computer will make the thermostat in your house rise by three degrees. But if, instead of that, you said, “Dang, it’s cold enough in here to freeze the fuzz off a snow weasel,” your house would definitely pretend it didn’t hear you.

The point is, we will soon interact with computers using a variety of inputs besides mice and keyboards, including the spoken word. But in the very near future when we speak to computers, we will have to speak to them in a dialect they can understand, just as we speak to dogs using special, limited vocabularies. And learning to code will make you much more fluent in this dialect.


Now: A day will come when computers also understand the part about the snow weasels; heck, in the distant future you will be able to pilot a cheddar drone using only your mind! But the road to that bright horizon is paved with a lot of zany mishaps. Meanwhile, learning to talk and think like a computer will immediately make you more confident and capable in a world full of helpful machines that don’t understand human language very well.

REASON 2: If you learn to code, you will make cool new friends!

A whole lot of people on the internet are coders and many of them spend a lot of time helping each other learn stuff. They’re usually smart and nice. And despite stereotypes to the contrary, most coders are also pretty hip.

Imagine a group of people who are so passionate about their work that they do it on the weekends, too, and then give the fruit of their efforts away for free to anyone in the world. Many coders consider this standard procedure. They do it because they love it and the community expects it of them. It is their way of influencing history. Like artists.

Now, imagine you are trying to learn to code and you run into a problem. If you diligently attempt to resolve it through reading and experimenting and you still can’t solve it, and then you ask for assistance in an online forum of coders, you will almost always get a friendly, helpful, and downright generous response from someone you’ve never met whose time is worth a lot of money. If you participate and contribute to that same community, you may even befriend or become such a person. You will thereby join a global fellowship of coders, and you can expect to receive a mysterious book of rites in the mail.

LIR: The Mysterious Maya Civilization: Pre-Columbian Era to 1825

REASON 3: Adventure, fortune and freedom await you!

There is no question that computer programming is a lucrative occupation for many people who are good at it and also for many who are not. As of this writing, a senior Ruby on Rails coder can make about fifty thousand dollars per hour. So if you like money or the things money can buy, you might want to get a job as a coder.

On the other hand, you may not care about money, in which case would you mind buying me a beer? Thanks.

That link you just clicked goes to InspirePay, a payment startup founded by Mark Fischer. Mark charges nothing for the service — so, since you’re buying, do you mind getting him a pint too?

Like many software entrepreneurs, Mark seems to be motivated in part by the sheer adventure of it. The world is stacked a mile deep in problems that software can solve. These problems will occupy software innovators for decades to come. Entrepreneurs like Mark are like early pioneers crossing the tall grass prairie, like legendary cattlemen on the high desert, like the first gold miners in the Sierras. They see the promise of adventure and they accept. They go first.

Learning to code gives you a gleaming toolkit to carry into this vast new frontier, a frontier where you will find countless opportunities to make a fortune and take wild risks. Sounds exciting, doesn’t it? I’ll drink to that.

REASON 4: If you learn to code, you can kill a lot of birds with one stone. More than two birds, anyway.

I have a friend who runs a software development firm. His firm specializes in PHP coding. (He doesn’t pronounce PHP as “fup”, but I do.)

Most software development firms get a lot of inquiries, and only a fraction of these inquiries turn into contracts. Along the way a firm often produces a proposal describing the work contemplated. This is a challenge: Proposal writing is repetitive, time consuming, and often fruitless.

So my friend wants to automate his ideal proposal generation process with a web application. He’s hacking on it nights and weekends using the laravel framework. Plenty of technology service companies do this kind of thing; some even make a business out of it it.

When he’s done, my friend will have:

  • A tool that satisfies his own business need, making his sales process more efficient and fun.
  • A software product that he can either give away to generate goodwill, or sell to generate revenue, or both.
  • Launch experience (which is the best kind) with a new coding framework (laravel) that he’s A) been looking for an excuse to work with and B) would eventually like to offer as a service to his customers.

Intimidating Swans

That is at least three dead birds; it could be more depending on how you count. So if you hate birds or something, now’s your chance to do something about it.

REASON 5: You have everything you need to start coding.

Computer programming is a difficult occupation, no doubt about it. But it does not take any more smarts than being an actuary or an attorney. It is probably less stressful than being a paramedic or a stockbroker. And it involves practically zero large predators, unlike zookeeping. Coding is mathematical and conceptual, abstract and very dynamic, and it is not for everyone. But look, you’re already on REASON #5 of a long and irritating six-reason blog post. You clearly have the most important characteristic of a good coder: speed-reading focus patience interest.

Are you reading this on a computer that is sometimes connected to the internet? (If not — if you’re reading this in print — I’d like to thank you. I’ve always wanted to be published on paper. It’s really, like, flammable, you know? Do you mind lighting a corner of it on fire right now? Wicked.)

If you have a computer that is sometimes connected to the internet and you’re truly interested in coding, then you have everything that most people who code ever had when they started. Most of them didn’t have computer science training. Many of them didn’t have college degrees at all, or even high school diplomas. All good coders are self-taught to some extent. With your computer and your interest, you can do just what they do:

  • Build a development environment — a sandbox where you can fling computer code around without harming other things on your computer that you care about. (You wouldn’t want to damage those blurry photos of enchiladas you took during that road trip to Tucson.) You can even try it out using an online sandbox.
  • Try and make something simple in code, starting from a tutorial online or from a crazy vision in your head.
  • Make lots of mistakes on the way, but who cares? You’re in the sandbox!
  • Read lots of documentation online.
  • Maybe ask some questions online, explaining that you already read the documentation.
  • Repeat these steps for a while, and do it again every time you want to learn something new.

Seriously, you can learn to code no matter who you are. Everybody starts somewhere.

REASON 6: The world needs more people who understand, care about, and can make things with the raw materials of our brave new society.

This cannot be overstated: Humanity has experienced only a few inflection points as important as the one that makes it possible for me to say this to you right now. No matter how you feel about the media, smartphones, blogs, Facebook, the internet or computers, you must understand that they are radically, rapidly transforming culture and society in every direction at once. Your financial transactions and the football scores and your precise location on earth, pictures of your baby and adoring comments from its grandmother, your job and your friends and your secrets, your final conversation with someone you love, groceries on store shelves, missiles in their silos, the stoplights and the cars waiting at them and the people sitting in the cars and the news on the car radios — all that and more every day is connected and controlled through an information network that humans created with code .

When it appeared, the printing press made written material much more accessible to many more people. Still, not everyone immediately learned to read and write. The people who did learn to read and write fully participated in the new world that the printing press made possible. They controlled economic activity. They made the government and its laws. They recorded the histories. They propagated the world’s religions. They owned a portion of the culture, and they fought for their part.

The ones who didn’t learn to read and write? Most of them saw their fair share of sunrises and sunsets, just like most people for most of history always have. But a universe of richness and capability eluded them. Fantastic novels, inflammatory pamphlets, laws and holy books: All were just mysterious symbols to the illiterate. Just like code is to so many people now.

Go to it! by drbexl, on Flickr

Today, too many smart people fear or disregard code, and shrug away their disregard as acceptable and normal. But code keeps food on our shelves. Code brings us all we know of world events. Code makes your smartphone possible. Code enables the unfettered personal expression we call a right. Code is the weapon that will win future wars. Code is the medium of future artworks. Code is the conduit of freedom.

Now, since you read this far, you obviously have plenty of time. So c’mon — why don’t you make some code? Here are a few places to start:

(This post was originally published on the dojo4 blog when I was the CEO of dojo4. I copied it here and refreshed it because I like it. It is adapted from a presentation I gave to a lunch meetup of the Boulder Chamber of Commerce’s 2140 group.)

You should learn to code.

Refactoring the authorization scheme

One of the platforms I work on at Mozilla is is Mozilla’s multi-constituent identity repository (or “phonebook”, as some prefer to call it). It is a simple profile-and-group management tool that serves data via a responsive UI and a read-only REST API. It houses about 4,000 user profiles: People who contribute to Mozilla in some way, whether staff or volunteer; people who consider themselves to be Mozillians.

Screen Shot 2013-10-14 at 2.34.07 PM

The post below is an analysis of’s authorization system, which I believe is broken, and a rallying call to fix it.

Summary has become a mature platform and a valuable source of information about people who contribute to Mozilla’s products and mission, and it is likely to be important to Mozilla’s ambitious contributor goals over the next decade. But has outgrown the authorization paradigms it started with. Therefore, in order to prevent data safety issues and questions about product integrity, we must design and implement an authorization system that accommodates current and future data and users. We should apply this system evenly to both the UI and the API.

Overview supports two classes of user account: unvouched and vouched. Anyone in the world can create a new account; that account will be unvouched, and it has very limited rights in the system (just a step above an anonymous browser). In order to be vouched, an unvouched user must find a vouched user who will vouch for them. In practice this means asking in IRC. Once a user is vouched, they have full permission to search and browse all data and can also vouch other users. also supports two classes of API consumer: Mozilla Corporation and Community. Mozilla Corporation API consumers can access almost every attribute of most users and groups in the system. Community API consumers can only access the vouched/unvouched flag of a user whose email address is already known to the consumer. As initially conceived, accessing the API as a Mozilla Corporation consumer would require the requester to be paid staff and the URL of the consuming application to be a URL.


Vouching has lost much of its practical meaning, since we have no shared understanding or documentation of what vouched means or when vouching is appropriate. Some users are vouched immediately upon asking for it, while others must demonstrate some record of contribution. In practice, getting vouched is unevenly applied and poorly explained. Once vouched, accounts remain vouched forever.’s current membership includes users who contribute daily or monthly; users who contributed in the past, but no longer contribute; and users who have never contributed beyond creating a account.

Corporation/Community API authorization has lost much of its meaning, too. The criteria for being a Corporation consumer are not clearly stated in a policy document, and the data provided to Community consumers are not rich enough to meet the needs of most Community requesters. These factors combined encourage an ad-hoc approach to API authorization (for example, this bug).

While the erosion of meaning in our authorization paradigms has advanced, so have the quality of the data we solicit and the promises we make about its protection. In the past year we added numerous fields to user profiles, and we have plans to add more. We also added per-field privacy controls to profiles, a measure intended to give individual users more confidence about sharing private identifying data. These are definitely working well in the UI, but we have not yet applied per-field privacy controls to the content of API responses.

These are data safety and product integrity risks that we must address.

By granting easy access to the platform (either by vouching or granting Corporate API access), exposes personal information that might not be shared if the actual exposure was clearly understood by users of the platform. We implicitly suggest that a trust network exists, but that network has an uneven (and low) barrier to entry; we implicitly suggest that API consumers will adhere to certain standards, but we do not strictly enforce these; and we explicitly declare that certain fields will be exposed to smaller groups, but we don’t yet apply these rules in the API. These are data safety and product integrity risks that we must address.


One obvious response to the problems described above is, “Stop vouching people who aren’t obvious contributors, and stop granting Corporate API access to Community API consumers!” But that response looks backward, not forward. has incredible potential as the single source of identity information across Mozilla’s varied constituencies — staff and non-staff, technical and non-technical, contributing daily or contributing just once, Foundation and Corporation. It is perfectly positioned to serve critical data about people to applications we haven’t even dreamed of. Look no further than the MozillaIndia Leaderboard (the subject of the bug linked above), which shows the most active contributors in India by mashing up bugzilla data with data.

The ClawIt doesn’t take much imagination to realize that any number of contributor tools and outreach efforts will benefit from more Mozillians with richer profiles. From simple ad-hoc mailing lists to ad-hoc group-based authorization; from mashups like the MozillaIndia leaderboard to a unified Mozilla events system; from identity unification in to Dr. Claw, the Mozilla Schwag Bot©, which automatically sends t-shirts to contributors when they achieve certain badges; from 4,000 Mozillians to 1 million Mozillians: It all depends on more inclusion and more API access, not less.

It all depends on more inclusion and more API access, not less.

This blog post marks the start of the conversation. It is accompanied by a tracking bug in and a discussion thread on the developers mailing list. I’ve turned off comments here, but would love to hear other perspectives on the mailing list.

Ultimately, we may need to replace vouched/unvouched with something else, and we will certainly need to reconsider how API users authenticate and authorize to get API data from It’s going to be a fantastic technical and organizational challenge.

What an exciting time to be a Mozillian!

Update: In response to subsequent feedback on various channels, I proposed a framework for solving this, plus a concrete solution.

Appendix A:

If you are a user and are concerned about the safety of your data, please don’t delete your account! You can take some simple steps to restrict access to your profile while we work through this bigger question:

  1. If you wish, you can change what applications (if any) can access your profile through the API. Look for the “Services” section in the Edit Profile view. But beware: Services like, and others may require API access to function.
  2. While API users are not currently restricted by per-field privacy rules, UI users are. You can change fields to be visible to either Public (anonymous) or Mozillian (vouched) users.
  3. Very few fields are required. You can choose what you share. As’s authorization scheme evolves, please consider sharing more information. Dr. Claw, The Mozilla Schwag Bot© won’t work without your t-shirt size and address!

Appendix B:

Dr. Claw, The Mozilla Schwag Bot© was conceived during the composition of this blog post for illustration purposes. Developers needed!

Refactoring the authorization scheme

Baby Sleeper Plans

bottomI promised last year to post the plans that I made when I built the baby sleeper that our baby slept on for the first six months of her life. Here they are! I made them in SketchUp, but doesn’t allow me to attach .skp files here so I’ve attached pictures instead.

This baby sleeper is designed to satisfy a handful of important requirements:

  1. It should fit commercially-available baby mattresses. We found a great organic mattress here sized 15″ x 35″, so that’s the size of this sleeper’s platform.
  2. It must prevent the baby from rolling off the sleeper onto the floor. So it has high walls on 3 sides.
  3. It should put the baby at the same height as her parents — the top of her mattress should be even with the top of the adult mattress.
  4. It must keep the baby mattress and the adult mattress right next to each other, touching. Any gap between the mattresses can be quite dangerous!

Adult beds come in all sizes and designs. We have a platform bed, and these plans are for our bed. Unless you have the exact bed we have, you will probably  need to modify this design. If your bed has a nice fat lip next to the mattress, one edge of the sleeper can rest on the lip. If your bed has a box spring, you will probably want to incorporate some flat slats of wood to go between your mattress and your box spring to help support the sleeper on the front. On the rear are legs that rest on the floor.

Construction details:

  • I made the entire sleeper box, platform and walls from scrap plywood. Every joint is glued. I used assorted deck screws from a pile on my workbench to pull the joints tight.
  • I made the legs from electrical conduit with a conduit socket threaded into a plumbing fixture attaching the legs to the the sleeper (see picture above). I wrapped the bottoms of the legs with an old bike tube to protect the floor. I added some felt pads to the front supporting edge, which sits on the lip of the platform bed.
  • I sanded the sleeper very smooth first with sandpaper and then with steel wool. I filled in big gaps with wood patch. I finished the sleeper with several coats of a tung oil finish, well rubbed. I let the finished sleeper off-gas in the sun and wind for several weeks.
  • In the photo above you will see some holes I drilled in the bottom of the sleeper: These are for stout rope which I used to tightly bind the sleeper to the lip of our platform bed. The photo below shows how tight a fit it was.

attached to bed

Here are some general instructions that may help adapt these plans to another bed:

  1. Measure from the floor to the top of your mattress. In our case it was 15 7/8″.
  2. Subtract from that measurement the height of the baby mattress you bought (for us it was 1 1/2″). The resulting number is the height that the platform must be off the ground. In our case it was 14 3/8″.
  3. Measure from the lip of your bed, or from the top of the box spring, to the top of your mattress.
  4. Subtract from that measurement the height of the baby mattress you bought. The resulting number is the distance between the platform and the bottom of your front edge support. The front edge support is either the box that rests on the lip of your bed, or the slats that slide between your mattress and your box spring. In the drawings below this is 4″ plus the thickness of the platform board (5/8″) and the thickness of the board at the bottom of the box (5/8″), or 5 1/4″.
  5. Measure from your front edge support (the lip of your bed or the top of your box spring) to the ground. The resulting number is the height that your sleeper’s legs will be, minus the thickness of any supporting materials. In our case the legs were 8 1/2″ after I subtracted the thickness of the extra support plank running along the rear edge.

This sleeper was a great way to keep our baby very close at night without putting her in bed with us.

Our baby enjoyed the baby sleeper that I built from these plans, but I cannot guarantee that you or your baby will. By viewing these plans you agree to accept all responsibility for any outcome resulting from your use of them; you agree that your family’s well-being is entirely beyond the control of any party involved in the creation or publication of these plans and instructions; you signal your understanding that these plans are provided here as-is with no warranty and are shared under a Creative Commons BY-SA 3.0 license. If you cannot agree to these terms and you want a great baby sleeper, buy one.


Baby Sleeper Plans


In an earlier post I described a project that produced a perfectly good result, but not the result required. This is inevitable — it will happen to everyone buying or selling creative work — and it can be quite demoralizing. As someone in the business of delivering custom services or products, figuring out what people want is the most challenging, most important thing you can do. And you can do it by repeating a single mantra.

A friend once asked a capable carpenter to install a door over a hole in the drywall of her basement where some plumbing valves were accessed. After a day of work she was aghast to discover that the carpenter had bought a full-sized closet door, built a frame for it, drywalled the frame, painted it and even installed a doorknob. The work was high quality and fairly priced. But she wanted a tiny little access hatch — a foot square, maybe — not a giant closet door. She paid the carpenter’s bill, then hired another carpenter to tear the door down and put in a little access hatch.

This has probably happened to you, too. Have you ever realized when your food arrived in a restaurant that you were hungry for something different? Have you ever begrudgingly paid for a service (a haircut, say) that is acceptable, but not what you really wanted?

what a mistake

It is easy to say, “The carpenter should have known his customer wanted a little access door, not a big closet door.” And maybe he should have. But should the barber have known what haircut you had in mind? Should the server have guessed that you wanted a different entree than the one you ordered?

Surely at some point in your journey you’ve thrown away days or weeks of work after a new detail or requirement emerged at the last minute. Almost everyone has. Why didn’t you know what to produce the first time?

Well, it’s because knowing what people want when they ask for something is hard. People often don’t know what they want, or don’t know how to ask for it. Delivering what they actually want requires you to interpret many layers of motivation and establish a shared understanding of the actual desire.

Arrow on flyer layers

Some of us are born with an innate ability to understand what people want very quickly. Others learn to do so by mastering a particular domain. Occasionally a shared understanding is based on a long relationship — it is easier to anticipate your friends than it is to anticipate strangers, after all. But for most of us, on most projects, establishing a shared understanding requires hard work. The sooner we do this work on a project, the less effort we waste.

Every project has a desired outcome — it’s one of the principal characteristics of a project. But in countless projects, the stated outcome would never be enough on its own to satisfy the sponsor or customer. Consider the following common projects:

  • Redesign the website
  • Rewrite the application using Python
  • Make a a new logo

They seem quite clear, don’t they? They’re just as obvious as, “Put a door over the hole in the wall.” It’s simple: Buy a door, frame it in, do some finish work. Make some new website designs that the customer likes. Reproduce the functionality in Python. Keep drawing logos until the customer likes one. Done and done, right?

Lorde Gelo

Bah. That isn’t a list of desired outcomes, it’s a list of implementation details. Those aren’t ends, they’re means. They’re the work you — the expert — do when you’re trying to deliver the thing. But they’re definitely not the thing you’re trying to deliver.

When someone asks you to redesign their website, ask them “Why?”.  They must have something in mind, something they think will happen if you redesign their website. How can you do a good job if you don’t know what that thing is? And when they say, “To make it look more modern,” you say, “Why?” Again, they must have some reason to believe they need a modern-looking website. And when they say, “So more people will visit the site and stay longer,” you say, “Why?” “Because if more people visit the site and stay longer, I can join a better advertising network.” “Why?”

Eventually, after playing 3-year-old for long enough, you’ll have your answer: “Because advertisements on this site are how I make my money, and I’m not hitting my goals right now.” Aha! It has nothing to do with modern design. Design is just an implementation detail. The customer wants to show different advertisements and thereby increase revenues; they think they can get there with a new site design; and they’re willing to invest in that theory. Now you can actually apply your expertise to the customer’s needs. Now you’re solving the right problem.

Almost always, asking “Why?” will reveal how faulty the initial project description was, and how far off-track you might have gone if you didn’t ask. That’s when you get to demonstrate the hard-won experience of a craftsman:

The Cutler's Hands

  • “You don’t need to rebuild the application in Python. You just need to add indexes to your database.”
  • “You don’t need a new logo, you need different colors.”
  • “You don’t actually want me to install a door there. You just need to cover this hole in the wall with a little access hatch, right?”

Extracting enough information to build the right thing can take a lot of time and may require asking and answering the same question over and over. During this exercise it sometimes feels like nothing is happening at all. But what is happening means everything to your project.

Sometimes, this approach simply won’t reveal the information you need to deliver a good project. And, unfortunately, you won’t know that until you’ve already done some work. So, in another blog post I will explain how inexpensive prototypes can help. Hint: Building the wrong thing allows you to ask, “Why not?”


A drawing of a house.

Somewhere in the clutter of my home office I have a beautiful design packet from a local architect. In big full color pictures it depicts my house with a wonderful modern roofline. Jutting points and angled planes, high windows and slabby overhangs. I love that roofline.

When I engaged the architect, I had already sketched about 12 floorplans for the addition we hoped to build. They were based on daily usage and known pain points. I knew exactly what spaces our house most needed: a mud room, a garage, and a new entryway. I also knew every constraint by heart: how far to the edge of the buildable lot, where the water lines ran, how many additional circuits our electric box could accommodate, which floor joist held the nearest hot air duct. My floorplans were optimized for utility, for ease of implementation. For us.


The architect took a look at my drawings and smiled. “They look good,” he said. “But it doesn’t matter right now. If you get the roofline right, the floorplans will fall into place.” Well, I thought this was very wise advice. And, sure enough, when the architect delivered the designs, the floorplans fell right into place underneath that wonderful roofline. His pictures resembled my sketches but had more light, more windows, more style. Beautiful!

Six years later, we still haven’t built that addition. A roofline like that with the high windows, the slabby overhangs, the complex angles — well, it doubles the cost of building. There was no way we could afford to build the house in those pictures. We didn’t. And we probably won’t. We paid a good architect for nice drawings of a handsome house that may never exist.

rooflineA couple times a year, I think about that wonderful modern roofline, and how it would look from the street. But you know what? I miss having a mud room and a garage far more often — almost every day, in fact.

The architect emails sometimes to ask whether we’ve made any progress. He hopes we will, because he would like to see that roofline soar just as much as I would like to fill the garage full of bikes. Nobody, even the guy who got paid for it, wants to see good work languish.

I’m sure this tale sounds quite familiar to most web designers, web developers and web project managers. Anyone who’s done a few web development projects knows what it feels like to realize, deep into a project, that it isn’t working. The product can’t be built as designed; maybe it can’t even be explained.

Excepting the anecdote above, house design and construction are usually terrible metaphors for web design and development. The apparent similarities simply don’t hold up under close scrutiny. We’ve been building structures for a few thousand years and most of us have lived in one before, and we are all beneficiaries of this vast experience. Even someone who has never considered how a house is built might anticipate that a waterproof roof should precede interior finish work, for example.

The same is not true for web development. There is almost no state of the art: We are making it up as we go, and we are going very quickly. To date, practitioners have made very few cultural agreements that are as obvious as “countertops on cabinets” or “closets in bedrooms”. The trade is young. We build web sites like people without nails and lumber and other standard components build homes: We take whatever materials we have at hand and stack them on top of each other until it resembles a structure.


There is another similarity between custom home design and custom web development that I would like to point out before leaving this particular metaphor behind: In both disciplines, establishing a shared definition of success is the greatest challenge and the most likely point of project failure.

The architect in my tale thought success meant delivering beautiful designs within a budget. In retrospect it is clear that success meant helping me figure out how to build a garage within a budget. Neither of us was insistent enough about establishing this definition. Neither of us knew we had different understandings until the drawings were printed.

In upcoming posts I will suggest some simple practices that can make web development projects work better. I’ll describe common features of web development projects that transcend the methodology à la mode. And I’ll talk about various ways to integrate design and development activities.

I will know I have succeeded if just one person says it has helped.

A drawing of a house.

The chance straw hat, once honored

In 1996, on Halloween, I found an orange straw hat at the top of a hill in an empty field in Boulder.

I was sitting in the field in fresh snow and I was fairly soused when my friend Matt caught up to me and shook me to my feet. Flakes came down fast. The bars had all shut and the streets were nearly empty. Snowfall muffled the normal noises of the sleeping city, deepening slumber and drifts and solitude. Matt and I stumbled away up the hill.

The hat appeared ahead of us at the top of a rise. I picked it up and dusted it off. Snow had filled any footprints that may have led to the hat’s original owner. Nobody was nearby. The world seemed no bigger than the cone of light under a streetlight, big enough for just us. I set the hat on my head and wore it home.

For many months the orange straw hat bounced and flopped joyfully through social occasions, delighting many. I remember one event where people were particularly appreciative: They kept slapping me on the back and complimenting my hat. That’s how I met a jolly gentleman named Gordo. Gordo and I spoke for a while and he told me that his business often took him to Mexico. He indicated that he liked my hat very much.

I was living a relatively docile life, and I remember wondering at that moment if things were a bit too tame for the orange straw hat. My business did not seem likely to take me anywhere near Mexico, for example. The world is full of hats in hat boxes; but the orange straw hat was made for adventures. I felt a tightness in my throat (from the hat’s chinstrap, I think) when Gordo lifted it off. The hat bobbed away with him.

• • • •

Some time later I did some traveling myself, mostly in the South Pacific. My way went through hurricanes and heat, around the perimeter of the great red desert, from island to island through crocodile swamps and over rocky volcanic ranges. I spent many long days in sunshine and many nights dancing. I could have used a good straw hat, but I’d let mine go with Gordo.

Then I came to China.

In China, wide straw hats were quite common. They were unanimously straw-colored. So when I saw the orange hat akimbo among books and bottles in a small apartment there, I had to look twice. Yes, it was the same hat. It had come to China with John, a friend I visited who also knew Gordo.

John told an incomplete tale of the hat’s long travels. It had been on many heads, to many places — to Mexico, to the coasts. It weaved in and out of view, always riding above a crowd of admirers, all the way to China. I smiled to think of it.

Then John grew somber. He related how an uncouth expatriate recently had upturned the hat and emptied a bellyful of booze into it. After that misfortune, no haste could have prevented the hat’s colonization by Southeast Asian jungle life. Its insides were as furry as a kangaroo’s pouch. It was no longer fit to wear.

This seemed a sad end to an illustrious career, and I was glum until an inspired onlooker suggested we have a pyre. Of course! We could not leave a hat of this caliber to rot slowly in some Chinese dump.

We hung the hat on a rusting post in the yard and tried to ignite it, but in its vegetated state it was as flammable as a lily pad. So we brought out a can of insect repellent bearing a likeness of General Mao and, wielding the spray like a blowtorch, took turns blasting the hat. We all shouted joyfully when the thing finally lit. The vapors of a well-worn, well-loved hat ascended to the heavens.

• • • •

From China I passed through Indonesia and spent several weeks in Bali. There was a club there, the Sari Club, which later was destroyed by a bomb. But the club still stood when I was in Bali, and I liked to stop there after dinner some nights to enjoy a cool coconut drink.

One night I went to the Sari Club and stayed until dusk. I didn’t like walking after dark in Bali: Once before on a dim sidewalk I had encountered a pack of predatory urchins who pulled on my arms, grabbed at my pockets and scratched me with their fingernails. I didn’t want to see them again and I was apprehensive leaving the club.

I walked quickly in the evening, through the winding streets, past crooked alleyways and dark open doorways. The island wind was wild, tossing grit and loose trash around. Suddenly a great gust tumbled a straw hat around a corner and straight towards me like a dog to a whistle. The hat hung up on my feet and stopped. Nobody came chasing after the hat. I picked it up. It was in fairly good shape. I put it on and nobody followed me.

That was a great hat. It had a tropical-print fabric band. It didn’t fit my head very well but I didn’t mind. It didn’t fit in my luggage either so I wore it every day, through Indonesia, from Sydney to Cairns and on to Fiji.

(photo by Ethan Crawford, 1998)

For the traveler in Fiji a straw hat is more valuable than almost any other article except perhaps flip-flops. And everyone I met in Fiji lost their flip-flops. I think there must be someone in Fiji who finds all those flip-flops. I wish that person would write a blog post like this one, describing their incredible luck with flip-flops.

• • • •

My luck is with straw hats. But I didn’t know this about myself when I realized, half a day after flying from Fiji, that I’d left my second straw hat there (along with two pairs of flip-flops). I made this depressing discovery in a Greyhound Bus station in Los Angeles. I rode bareheaded and brooding across the vast salt desert of America.

But two days later, pedaling a bike in Boulder, I found a third straw hat. It was sitting unattended on a low wall by the side of the road.

I skidded to a halt and shot a querulous look at a man waiting nearby for the bus. He stared back blankly. Watching him all the while, I slowly picked up the hat and put it on. He stared back blankly. I made a gesture by which I intended to communicate to him that I was about to ride away on my bike with this found straw hat, and he had only an instant to prevent it. The man replied with a blank stare that clearly said, “What straw hat?”

I still have the bus-stop hat. It fits very well, but I’m afraid I have handled it roughly, packing it and wearing it often. I hardly trust it outside the house anymore. A few brittle straws break every time I pull it on. One day soon the brim will tear entirely away from the cap. When that happens I will dignify its demise somehow, though probably without General Mao-brand bug spray.

Anyway, the bus stop hat is retired. One day as I drove on a mountain highway, the driver of a Porsche Cayenne made an inconsiderate turn that forced me to brake quickly. As the Porsche sped away, a straw hat flew off its roof. I pulled to the side of the road and watched in anguish as speeding cars passed over the hat, which cartwheeled in their wakes.

None squashed it. In a lull I leapt into the road and snatched it up. It fits fairly well. It has a camouflage band and a leather forehead pad and it is the most expensive straw hat I have ever worn.

• • • •

The years go by. Nowadays I wear the Porsche-driver’s straw hat infrequently, but it was never meant for great adventures anyway. It had its terrifying moment, dancing in thin air with metal death all around. Now the hat is safe in the basement. It comes out for lawn games. It travels a pleasant circuit from the patio to the porch.

I don’t suppose that I am the only person who has good luck with straw hats. I’m sure there are others. But among the people I know, I have the best by far. Straw hats just find me.

In idler times I have wondered about this luck. If every class of thing has a deity — if there is a god of teacups, of tarantulas, of teeth — these motley divines are surely starved for ceremony. Any gesture will suffice to gratify them. But with such small domains to lord over, these deities can reward us with only the oddest fortune. The chance straw hat, once honored, always returns.

The chance straw hat, once honored

More than a job.

While copying various old work from an old Macbook to a new Macbook today, I ran across a short note I wrote myself back in 2009. I remember typing it. I’d just met Christian Heilmann, who was visiting Denver to speak at a conference. He gave a talk that must have impressed me, because I jotted some instructions to a future self: “Consider Mozilla,” I said.

But I’m getting ahead of myself.

Earlier today, before the episode with the Macbooks, I found myself in an unfamiliar place, surrounded by dozens of strangers. They led me up to the front of the room and told me to stand on a big black X. I did so. A trio of cameras panned and zoomed, and everyone in the room looked at me. I saw my face on the big screen, as did hundreds of people watching from home. I smiled a bit nervously and waved. They smiled back.

They were welcoming me. That’s how they welcome folks to Mozilla. Everyone present had stood on the X at one time. Some might even have given a speech from that X, but I kept my mouth shut.

Today was my first day at Mozilla. I am a web product engineer. I’ll help Mozilla’s many product owners articulate their vision for web sites and applications, and then collaborate with Mozilla’s many, many contributors inside and outside the company to launch new features and products on the web. This job is some web engineering and some web project management, plus a smidgin of every other aspect of web production from architecture to marketing. In fact, it’s precisely what I loved doing at dojo4 and in earlier roles, too. I couldn’t have written a more suitable job description for myself. And I’ve been nothing but impressed by the caliber and quality of people I’ve met at Mozilla.


I built my first website in 1995. It had a rainbow-tastic horizontal rule powered by animated GIF. I’ve spent my entire career working on internet technologies. Needless to say, the web has grown up in that time and has become utterly essential to the stability of many social systems. Our government, economic, and communication networks rely on services that themselves depend on open systems and common protocols.

But these foundational elements are not guaranteed. Plenty of powerful interests would prefer to have more control over the way we interact with information. They’d like to choose the tools we use, the voices we hear. But, so far, in this part of the world, the internet remains a wild and free place where submission to such controls is mostly voluntary. This is due in large part to the efforts of a staunch cohort of benevolent technology organizations and individuals who build standard-based tools with open sourcecode. Mozilla is one such organization.

Mozilla HQ Mountain View

This work is important and valuable. It has a clear purpose, one that I support. And there’s plenty of work to do. Mozilla has strong competition for its major products and some very ambitious new releases coming up. I’m thrilled to be here pitching in.

I should mention that I’ll still be working in Boulder. It’s home. Look for me anyplace that serves Boxcar coffee. If you’re a Mozillian, you can also find me in IRC at hoosteeno.

I also wish to thank everyone I met with during the past 3 months. Many, many people made time to talk with me about opportunities within their organizations. I am grateful.

More than a job.

A Rich Public Domain

@randfish posted “Where does Creativity Come From?” today, and linked to Kirby Fergusun’s excellent TED talk, “Everything is a Remix”:

Fergusun’s talk reminded me of this wonderful 2004 video tracing the history of a single drum loop, the “Amen Break”, as it travels from its original recording into a variety of illegally appropriated and infringing remixes and samples during the next several decades:

I could reminisce at great length about the 3rd Bass and N.W.A. songs this video digs up. I spent many days skateboarding around Denver, feeling very tough with that era’s hip hop playing in my head. But lately I’m more interested in the conversation about ownership and creativity these two videos consider.

I’ll dig back into this subject in coming months — not as a legal expert, just as a regular dude who cares about our culture’s ability to create new wonders unencumbered by short-sighted copyright and patent enforcement.

Listening to the second video again today, I was struck by a quote near the end. Here it is:

“Overprotecting intellectual property is as harmful as underprotecting it. Culture is impossible without a rich public domain. Nothing today, likely nothing since we tamed fire, is genuinely new: Culture, like science and technology, grows by accretion, each new creator building on the works of those who came before. Overprotection stifles the very creative forces it’s supposed to nurture.”

– Alex Kozinski

A Rich Public Domain