Jeremy Kahn's Dev Blog

There's always a method to my madness.

The Fear of 1.0.0

Lately I’ve been working to bring some of my JavaScript libraries to version 1.0.0. This is an important step in the life of an open source project. According to Semver, 1.0.0 defines the public API and therefore communicates to users that the project is stable. Additionally, it states that the API will not change in an incompatible way until version 2.0.0. And from 2.0.0, the API will not change until 3.0.0, and so on.

Semver is a logical and straightforward versioning specification designed to prevent “dependency hell.” The good news is that many projects do adhere to Semver, or at least something pretty close to it. While being generally beneficial, it inadvertently creates a new problem: Developers are hesitant to increment their projects to 1.0.0 and stay in 0.x.x for a very long time, and possibly forever. Many open source projects languish in the 0.x.x state because the developer lost interest and stopped working on it. This stifles community adoption because it means that a stable public API was never defined.

Commitment issues

Why do so many projects fail to reach 1.0.0? According to rule 4 of the Semver spec:

Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.

This means that the developer isn’t obligated to follow any rules with regard to the changes they make to a codebase. They are free to add, remove and completely change functionality with breathless enthusiasm. As a developer, I can tell you that this is quite a bit of fun. 0.x.x allows you to experiment and try new ideas. Once you hit 1.0.0, though, the fun is over and you need to follow the rules (of Semver). All changes must be carefully considered, justified and documented. Any incompatible API changes require a major version bump, which increases the potential for user base fragmentation. Version 1.0.0 is where a project grows up and discovery and experimentation tend to subside. It’s not hard to see the appeal of staying in 0.x.x forever.

What, then, is the drawback of 0.x.x? It means that a project cannot be trusted. It would be unwise for a business-critical application to have a dependency that is young and prone to significant changes at any time. It also indicates that the dependency project simply isn’t done and might not be ready for use. Part of getting people to use your work is getting them to trust you as a developer, and the version number plays a part in gaining that trust.

When to move to 1.0.0

Knowing when a project is ready for its first stable release is difficult and depends on the project. Small projects may be worth stabilizing after a few iterations, and larger projects may take a few years. Backbone.js, for example, took about 2.5 years. My own project, Shifty, took about that long as well.

Determining when a project should be considered stable isn’t a matter of time, it’s a matter of maturity. Most projects eventually reach a point where significant changes become less frequent and the development direction becomes more clear. If not, that might be a sign that the project needs a clearer focus. In any case, it’s the point where the code becomes less volatile that 1.0.0 should be considered. However, tagging the 1.0.0 release too early is even more harmful than waiting too long.

One way to guage when a project is stable is by monitoring how others use your code. If you’re lucky, users will tweet or email you questions about your project, or blog posts will be written about it. More likely, you’ll have to find alternative approaches to learning how others use your work. In my case, I do Github code searches for projects that use my libraries. It’s not glamorous, but it gives me insight into how my projects get used in practice and how I can tailor my APIs to suit real users’ needs.

A case study: Kapi

Kapi is an older JavaScript animation library I wrote. Kapi was the precursor to Rekapi (“Rekapi” is short for “Rewritten Kapi”). I was committed to getting Kapi to 1.0.0 and worked feverishly to build the feature set that I had envisioned for that release. After a few months, I finally got it to that point and released 1.0.0. I was still working on Kapi quite a bit at that time and wanted to keep adding features. However, it became apparent that adding the features that I wanted to would involve changing the API in incompatible ways, necessitating rapid major version bumps (2.0.0, 3.0.0, etc.). I realized that I had made a mistake by releasing 1.0.0 too early, but it was too late to go back.

My biggest failure with Kapi is that I didn’t wait for real user feedback. I built what seemed like an ideal design in my head, but it was never validated by actual users.

I ended up scrapping Kapi and went on to build Rekapi, which is designed to provide similar functionality to Kapi, but with a better development process. Currently, after over two years in development, Rekapi is still 0.x.x (though I will be focusing on wrapping up the 1.0.0 release in the near future).

Misconceptions about 1.0.0

For me, a 1.0.0 release has some unnecessary baggage associated with it. I tend to associate 1.0.0 with a finished project, including tests, documentation, a nice landing page, and a lot of sample code. While all of that is certainly important in its own right, these extra components of a project actually have nothing to do with the version number. The version number is a reference to the state of the API, not the state of the project. Semver doesn’t state any requirements for the quality of the documentation, it simply requires that it exists. It also doesn’t have any rules for tests, sample code, demos, a logo, IRC channel availability, or any other nice-to-haves that open source projects often provide. 1.0.0 is just a statement about the stability of the API — you are free to put off creating the extra content until whenever you get around to doing it.

This isn’t to say you shouldn’t writes tests and tutorials, they are invaluable for guiding your API decisions. Just don’t let that be what prevents your 1.0.0 release from ever happening.

Importantly, it is completely reasonable to increment the major version number. Emacs is currently at version 24, and Chrome is in the 30’s. You are allowed to make public API changes after 1.0.0, just do it judiciously and adhere to the rules of Semver.

Don’t forget to ship

With all things in software development, shipping is key. In open source, tagging the 1.0.0 release is comparable to shipping a final product. It’s natural to want to iterate on something endlessly, working towards that state of perfection that’s just out of reach. But every so often, we as developers need to take a step back and consider if what we have in front of us is as good as it needs to be. If it is, then it’s time for 1.0.0.

Software and Amplification

Programmers exist to automate work. This isn’t a new idea, but it took me a while to understand this simple concept. Programming with automation in mind has subtly caused me to make smarter, clearer decisions when designing a solution. This idea of automation has also helped me make better UX decisions. Even as a strictly non-designing developer, I have to do some degree of UX design in my work — sometimes a mockup takes a UX detail for granted, or I’m just working on a personal project without the help of a designer. In any case, keeping my automation imperative in mind has resulted in more effective results.

It’s extraordinarily useful to have a guiding motivation or philosophy. This is the single most valuable lesson I’ve learned from Bret Victor. I realized recently that, as a software developer, I have the potential to not just automate work with machines, but to amplify my efforts though other people.

Amplification, in a general sense, means to take a signal and increase its strength. Lots of tools allow us to amplify ourselves. Amplifiers in the context of music create a greater sound signal, but this is just a literal way of interpreting the concept. The printing press allowed Johannes Gutenberg to amplify the message of the bible in the 1400s, and radio amplified the reach of popular music in the 1900s. In either case, technology amplified a message in such a way that many more people were able to receive it than was previously possible. To me, the amplification potential of the web is what makes it the most interesting technology in human history.

There is more to amplify than ideas, though. Software, thanks to trivially easy digital reproduction, allows us to amplify processes. If I find a solution to weird CSS bug, I can make a Github Gist and share it with the world about as quickly as I can type it. If my solution becomes ubiquitously known, nobody ever has to spend the time to solve that problem ever again. This is why you don’t ever have to worry about CSS resets. A software solution can be reused an infinite number of times. As a mortal, I think that’s pretty cool.

While this is all nice and idealistic, things get a little more complicated when you consider that quality is amplified as well. High-quality software solutions can make the world a much better place. Linux, Firefox, and jQuery come to mind. These projects aren’t perfect, but their positive impact on how the world works is undeniable. On the other hand, low-quality solutions can create significant problems that last for decades.

At Jellyvision, I build JavaScript frameworks all day. This is a dream job for me, but it’s also a huge responsibility. I develop tools that the rest of my team depends on to work and be effective. If I do a good job, everybody is happy and productive. I do a poor job, everyone is slowed down and my code is quickly considered “legacy software.” Because of this, I work very carefully. I spend as much time writing documentation as I do code. I iterate on my ideas and don’t ever consider something “done.” I also make sure to share my work frequently and get feedback from the people who will be depending on my code. This works out nicely, as it doesn’t just result in better work, it makes my job easier and more enjoyable by providing clarification and direction.

If you build tools, you are amplifying your solutions through others. Lots of people using a high-quality tool results in high-quality collective output, but the inverse is also true. There’s a growing sentiment in the software world of ”just ship it.” Shipping is important, but it must not preclude quality. The code you write may be used by millions or even billions of people, and it may happen faster than you think. When you consider how much collective human time your work may cost or save, it isn’t unreasonable to take a breath, reconsider your ideas, and get the job done right the first time. I’m not advocating that we all spend an inordinate amount of time tweaking and perfecting. With all things, balance is key. Ship, but don’t ship shit. And remember that finding out who introduced a bug or made an ill-considered design decision is just a git blame away.

Creating CSS Animations With Just Your Mouse

Animation is an inherently visual art, and I believe that there need to be visual tools to assist us in creating them. Not unlike Bret Victor, I think that the gap between the input and the output of the creative process should be minimal, and iteration should be painless. I’m also incredibly lazy and believe that making animations (or anything, for that matter) should be quick and easy. I develop an app called Stylie in my free time, a tool that tries to satisfy these ideals. Among other things, Stylie lets me stretch my creative legs with regard to UI/UX design. I’m not a designer by any means, but I can generally identify UI elements that obviously do or don’t work.

All of the UI decisions I make with Stylie are deliberate and carefully considered. I like the current UI, and I’m careful about cluttering it up with unnecessary or awkward features. In other words, I don’t want it to become The Homer. At the same time, I want to automate as much of the process of scaffolding an animation as I can, because I use Stylie quite a bit and get annoyed with repeating certain actions over and over again. Ironically for an adamant Vim user, I’ve found that using my mouse to work with the UI is far easier than using the keyboard to tweak an animation, so I’ve worked to optimize that workflow. In doing so, I inadvertently developed a way to develop complex CSS animations without using the keyboard at all.

My Stylie workflow

While Stylie is a web app and will work on any modern browser on any desktop platform, I develop it on OS X. Therefore, Stylie has an even more optimized mousing experience on late-model Apple laptops and desktops with a Magic Trackpad. If you are on OS X, you can enable three-finger dragging:

This feels weird at first, but once you get used to it, you’ll have no idea how you got by without it. It makes the overall dragging experience feel more natural and gestural. When using it to select blocks of text, it feels like you are “drawing” around the text you want. Happily, three-finger drag works perfectly with Dragon, the jQuery dragging plugin that powers Stylie. It’s not magic, three-finger drag just invisibly inputs the initial click that would initiate a drag motion. This makes any interface that requires lots of cursor dragging much more elegant, so I highly recommended enabling the feature.

The first thing I’ll do is create however many keyframes I’ll need (by clicking the “+” button in the upper right of the Keyframes panel or hitting “K” on the keyboard) and drag them around with three fingers. However, the positioning of the points often needs some finessing, so I’ll usually have to tweak the corresponding values in the Keyframe panel. There are several ways to interact with Stylie’s number fields, all of which are designed to be similar to Chrome Dev Tools:

  • Re-type the value
  • Hit “up” or “down” on the keyboard to tweak the values
  • Hover the text input with the mouse and scroll up or down to tweak the values

The last method is the most useful for me, as it’s both quicker and more fun than switching to the keyboard to change the values. Personally, I wish I could scroll the mouse to increment any number input on the web, so I built it into Stylie.

So, rather than clicking around and re-focusing the various number fields (which there are a lot of), I’ll just hover my mouse and “scroll” the values. This feels like a much more efficient and natural way to tweak numbers, to me. This is particularly useful when modifying rotation values (RX, RY, and RZ for each keyframe).

Next, I’ll tweak the easing formulas. Stylie supports all of the “classic” Robert Penner formulas, but you can also create your own with the curve tool.

To use a custom easing curve, just link it on a per-property basis in the Keyframes panel. The drag handles on the easing tool work the same as the keyframe crosshairs, so you can three-finger drag those as well, or just scroll the number fields.

A lot of animations also call for some kind of rotation. While you can achieve full three-axis rotation by tweaking the keyframe number fields as I explained earlier, it’s easier to hold the Shift key on the keyboard (I know, I’m going against the title of this post) to bring up the rotation Cubelets. You can just click and drag (or three-finger drag!) the Cubelets until they face the way you want for the various points in the animation.

Once I’m done with tweaking an animation, I’ll grab the generated code from the CSS panel and I’m done. With this workflow, I’ve found that using Stylie is a fluid and somewhat gestural way to quickly create and tweak an animation. Rapid prototyping and iteration is a key component of making animations that work well within a game or application, and I hope to keep developing Stylie to explore what other methods are effective for simplifying what is normally a pretty painful process.

Open Source and Respect for the User

As I’ve noted in the past, open source is as much of a moral issue for me as it is anything else. I feel morally obligated to write and distribute open source code. I’m a bit of an idealist, but I also realize that this principle can be at odds with modes of business, and, by extension, basic survival.

You need money to survive in this world. Freely distributing software is generally not directly profitable, but it is possible to profit from it by offering support and other services around the free software. This isn’t a silver bullet, though. Not every developer wants to provide services for a living, as it may not fit well with their skill set, interests, or other constraints. For instance, an open source developer might not feel comfortable directly working with or for others, and instead prefer to focus on product development or other solitary means of income. There needs to be another way of making money with open source software, one that is not at odds with respecting the freedoms of users and sharing useful tools with the community.

Let’s say that I want make my living by starting and running a website. For argument’s sake, let’s say I’m building a social network for coffee shop enthusiasts (yes, I am writing this in a coffee shop). To make this website, I need a server and a UI. I own and control the server, but the UI code runs in users’ browsers. It wouldn’t make much business sense to freely distribute all of the code I write, as I would be giving away any competitive edge I might make for myself. At the same time, I don’t want to opaquely control users’ machines without making it clear what my code does. In other words, users should have free access to the source code of the HTML/CSS/JavaScript that they are downloading and running in order to use the website I’ve built.

I feel that a reasonable compromise in this situation is to share the UI code, but not the server code. Computer users have the right to know everything that their machine is doing. It’s their property, it should not be made arbitrarily mysterious to them. While most users are not technical enough to understand what a piece of software is doing and will probably never care, there should never be a limitation that prevents them from doing so. However, users do not control or own the server of a web service. I do not feel as obligated to share that code with them. It would certainly be nice to do so, and in some cases it is feasible, but sharing remote server code (in this example) would jeopardize my income and livelihood.

Free software, as defined by the FSF, feels ideologically pure to me. I want to live in that world. But we live in a world where competitive edge matters, and giving away the entirety of your product is not a viable business model in a lot of cases. A more realistic compromise is to open source the code that a users’ machine will execute, but not the code that runs on a remote server that a service provider controls.

A potential gray area with this approach is service provider trust. If I as a user can’t see what the developer’s server is doing, then my data is at risk of being used in ways that I do not consent to. While there is no failsafe way to guard against this, it is the responsibility of a service provider to provide a Terms of Service document explaining what they will and will not do with users’ data. It is the responsibility of a user to read and agree to that document before using the service. Users should always be able to opt-out of a service if they don’t feel that it provides what they want, or if using it is not in their best interest.

As a programmer who loves what he does, I want to share as much code as I can. I also don’t want to starve. Dogmatically adhering to the principles of all-open or all-closed software is divisive and bad for the software development ecosystem. I think there is a better way to develop software that respects the interests of both users and developers: Compromise.

60 FPS or Bust: Dynamically Prerendering CSS Animations

Creating better animations for the web has been something I’ve been working on for a few years, and I’ve just figured out a new method that offers more flexibility and animation fidelity than was previously available. I call it “CSS prerendering,” and it’s easier than you think.

CSS vs. JavaScript animations

In the beginning, there was JavaScript. For years, JavaScript was the only way to add animation to a web page. As web standards matured, CSS become more featureful and offered transitions and animations. These browser-native CSS features are capable of delivering much smoother animation than JavaScript, because the browser seems to be able to optimize native animation. However, CSS animations and transitions are not terribly flexible, leaving developers to choose between a smooth, 60 frames per second animation, or an animation that can adapt to the needs of an application on the fly.

CSS animations (@keyframes) are inflexible because they must be hard-coded. Transitions are a little easier to work with, as they can gracefully respond to any CSS changes performed by JavaScript. However, the complexity that CSS transitions can give you is pretty limited — an animation with multiple steps is difficult to achieve. This is a problem that CSS @keyframe animations are meant to solve, but they don’t offer the level of dynamic responsiveness that transitions do.

CSS @keyframe animations are also limited by the native easing formulae available — there are only six. This is not enough to meet the needs of all designs. Joe Lambert came up with a way around this with Morf; a tool that generates a @-webkit-keyframe animation with many tiny steps. This opens the door to an unlimited selection of easing formulae. I decided to build on top of this idea with Rekapi’s Rekapi.DOMRenderer.toString feature, which uses a straightforward keyframe API to generate cross-browser compatible CSS code. I then used that functionality to create Stylie, which provides a UI to create animations and exports it to CSS code.

CSS prerendering

The idea behind CSS prerendering is pretty straightforward — you create a CSS @keyframe string at runtime with JavaScript, inject it into a dynamically-created <style> element, and then insert that element into the DOM. When the animation is complete, you simply remove the <style> element from the DOM. This approach works surprisingly well, particularly in WebKit-based browsers (other rendering engines still need to catch up).

Until now, there haven’t been any tools that I could find that can do this, so I decided to fill this void with Rekapi’s DOMRenderer module. Rekapi’s goal is to provide a usable and flexible API for creating keyframe animations, and historically it only performed JavaScript-based animations. With the DOMRenderer, you can use the same API to create a CSS @keyframe animation, making for magically smoother animations that don’t block the JavaScript thread. But don’t take my word for it, you can see the difference for yourself. The difference in quality is far more pronounced on mobile devices, especially iOS.

Creating a CSS animation with Rekapi

To create a CSS @keyframe animation that works in every browser, you need something like this (generated by Stylie):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
.stylie {
  -moz-animation-name: stylie-transform-keyframes;
  -moz-animation-duration: 2000ms;
  -moz-animation-delay: 0ms;
  -moz-animation-fill-mode: forwards;
  -moz-animation-iteration-count: infinite;
  -ms-animation-name: stylie-transform-keyframes;
  -ms-animation-duration: 2000ms;
  -ms-animation-delay: 0ms;
  -ms-animation-fill-mode: forwards;
  -ms-animation-iteration-count: infinite;
  -o-animation-name: stylie-transform-keyframes;
  -o-animation-duration: 2000ms;
  -o-animation-delay: 0ms;
  -o-animation-fill-mode: forwards;
  -o-animation-iteration-count: infinite;
  -webkit-animation-name: stylie-transform-keyframes;
  -webkit-animation-duration: 2000ms;
  -webkit-animation-delay: 0ms;
  -webkit-animation-fill-mode: forwards;
  -webkit-animation-iteration-count: infinite;
  animation-name: stylie-transform-keyframes;
  animation-duration: 2000ms;
  animation-delay: 0ms;
  animation-fill-mode: forwards;
  animation-iteration-count: infinite;
}
@-moz-keyframes stylie-transform-keyframes {
  0% {-moz-transform:translateX(0px) translateY(0px);}
  100% {-moz-transform:translateX(400px) translateY(0px);}
}
@-ms-keyframes stylie-transform-keyframes {
  0% {-ms-transform:translateX(0px) translateY(0px);}
  100% {-ms-transform:translateX(400px) translateY(0px);}
}
@-o-keyframes stylie-transform-keyframes {
  0% {-o-transform:translateX(0px) translateY(0px);}
  100% {-o-transform:translateX(400px) translateY(0px);}
}
@-webkit-keyframes stylie-transform-keyframes {
  0% {-webkit-transform:translateX(0px) translateY(0px);}
  100% {-webkit-transform:translateX(400px) translateY(0px);}
}
@keyframes stylie-transform-keyframes {
  0% {transform:translateX(0px) translateY(0px);}
  100% {transform:translateX(400px) translateY(0px);}
}

…And then paste that into your CSS code. That’s just for one, very simple animation. Here’s how that same animation might be set up with Rekapi’s DOMRenderer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var rekapi = new Rekapi(document.body);
var actor = new Rekapi.Actor(
    document.getElementsByClass('stylie')[0]);

rekapi.addActor(actor);
actor
  .keyframe(0, {
      transform: 'translateX(0px) translateY(0px)'});
  .keyframe(2000, {
      transform: 'translateX(400px) translateY(0px)'});

// Feature detect for @keyframe support
 if (rekapi.renderer.canAnimateWithCSS()) {
   rekapi.renderer.play();
 } else {
   rekapi.play();
 }

Rekapi handles all of the vendor prefixing for you, so you only need to write an animation once. And if the browser doesn’t support CSS animations, Rekapi will gracefully fall back to an old-fashioned JavaScript animation, which it has always supported. To see what kinds of complex animations Rekapi can handle, I encourage you to check out Stylie, which is simply a graphical front end for Rekapi.

Better animations

CSS lets developers and designers create fluid, efficient animations that don’t block the JavaScript thread. However, we have lacked the tools to make them easy to work with. I really want to solve this problem, and I think that Rekapi and its DOMRenderer significantly narrow the gap between performance and flexibility. I hope that CSS prerendering becomes more widely used, as it enables a much smoother web experience. I’d love to know how CSS prerendering works for you, and if you find any bugs, please report them. Happy animating!

Update: Rekapi has reached 1.0.0 after this post was originally published, and the API for CSS prerendering has changed somewhat. The article has been updated for accuracy.

Open Source as a Civic Duty

I occasionally get asked why I spend so much of my free time writing software and giving it away for free. There are a number of reasons for this — I like to build things and I use it as an excuse to practice and improve my skills — but one of the most driving motivators for me is that I see open source contributions as a civic duty, a moral obligation to the rest of the world.

Considering that I am an employed programmer living in Silicon Valley that is generally thought to not be incompetent, you could deduce that I’m not worried about how I’m going to pay for my next meal. I’m not rich by any stretch, but I have a reasonably comfortable lifestyle, and that’s all I’d ever really want. After all, does a programmer need much more than a laptop and a cup of coffee to be content? Given that I’m not stressing about whether or not I’ll have a place to live and food to eat next month, I’m among the most fortunate people in the world. And if you have access to the technology needed to read this, you probably are too.

Morality is a touchy subject that varies widely among individuals and cultures, and this post is not meant to imply that my sense of morality is necessarily correct. However, I feel that people who are fortunate enough to survive on their own means have an obligation to give back to their community. I believe that some degree of self-sacrifice and civic duty is necessary to build and maintain a community that we all want to live in. This can come in many forms — giving to charity, doing volunteer work, or in my case, writing free software. It doesn’t really matter how you try to contribute to your community, it just matters that you are doing it.

Granted, I’m not writing software that will deliver clean water to poor countries in Africa or help cure Malaria. I tend to focus on web animation tools and other UI utilities. However, I’m doing work so that others don’t have to. My goal is to save time at scale so that other people can solve different problems that don’t yet have solutions. To take an extreme example, consider the GNU Project. As a whole, GNU has saved humanity man-centuries worth of work. There’s very little time spent developing operating systems and basic utilities anymore, because that is mostly a solved problem. Instead, we use GNU tools that others have spent the time to build, freeing us up to pursue other challenges like statistical modeling and AIDS research. If you have doubts about the value of free software, just look at GNU.

Altruism is, unfortunately, not a terribly common value in Silicon Valley. At best, larger companies will have a branch dedicated to positive social impact, and smaller companies may have the occasional charity fundraiser. But it seems that a large portion of Silicon Valley tech companies are focused on some self-serving vision or niche problem that only the founders and their friends have. I don’t want a culture where the only problems being solved are the ones that tech people have. I feel that writing free software on my own time is a tiny step in the right direction, even if indirectly. My dream is that someday, a free tool I’ve written will be used to help do something truly valuable. Anyone can do this, it doesn’t require much money or time — just a sense of the bigger picture.

Setting Up a Local Development Environment in Chrome OS

Cloud-only operating systems are a great option for most people. Web apps are slowly replacing native apps, and that trend is likely to continue. However, one type of user that will have a hard time migrating to the cloud is software developers. So many of our tools are local command line utlities, and they don’t really work in the context of a web application. I tend to treat UNIX as an IDE, and this methodology is at odds with the concept of cloud-only operating systems. I can’t see myself ever giving up tools like Vim or Git, or the simple elegance of piping the GNU Coreutils. Cloud-based IDEs like Cloud9 are cool, but they don’t give me the control that I get from a UNIX-like environment.

The common workaround for this is to SSH into a remote server via the browser, but I feel that this is a fundamentally flawed way to develop software. This approach requires you to buy and maintain two machines instead of one. More importantly, your productivity is limited by the quality of your internet connection. If you are in a coffee shop with spotty wifi or just enjoying a nice day in the park with your laptop, you won’t have easy access to your tools, if any at all.

I got a Chromebook over the holidays, and one of my concerns was that I wouldn’t be able to code on it effectively. I don’t really have much use for a laptop I can’t code with, so I started looking into ways to get Ubuntu loaded so I could enjoy my Linux tools unencumbered. I tried installing a Chromebook-optimized version of Ubuntu, but it was kind of buggy and I felt like I was missing the point of the Chromebook. I removed Ubuntu and instead tried Crouton, an awesome little tool written by David Schneider. Crouton makes it painless to install a chroot Ubuntu environment on Chrome OS. In other words, it creates an Ubuntu file system inside of Chrome OS’s file system and logs you in. When logged into the chroot, you are effectively running Ubuntu. It’s not virtualization, as Ubuntu has full access to your hardware resources, which can be a bad thing if you’re not careful. If you are careful, it works amazingly well. You can even run a Unity environment (or whatever GUI you want, Crouton lets you choose) and graphical applications. You can easily toggle between the Chrome OS and Ubuntu environments with a keyboard combination. What really matters is that you can run OpenSSH and easily interact with it from Chrome, even when you are offline.

This post serves as a guide for two things: Setting up the basic chroot environment with Crouton, and some setup I needed to perform in order to get some development tools running. There were a few issues that needed to be worked out because this is admittedly a backwards way to do things, and the Ubuntu environment installed by Crouton is a little bare-bones.

Getting started with Crouton

The first thing to do is boot the Chromebook into Developer Mode. Doing this will wipe the device, but that doesn’t really matter because everything is backed up to the cloud and gets synced back down when you log in. This is the process I had to follow for my model, and yours may be a little different - just Google for it. You don’t need to worry about setting up the firmware to boot from USB. Once you are in Developer Mode, sign in and hit Ctrl + Alt + T to fire up the shell. Type shell to be dropped into a BASH environment. At this point you need to follow the directions in Crouton’s README, but here’s a quick rundown of what you need to do in the shell we just opened:

1
sudo sh -e ~/Downloads/crouton -t unity

Go for a walk at this point - this will download about 700 MB of files. Once the process is complete, you will be prompted for the root user name password. Enter that, a few other bits of user info, and you’re done! Since we installed Unity, we can fire that up with:

1
2
# The `-b` backgrounds the process.  You can omit it.
sudo startunity -b

You can switch between the Chrome OS and Ubuntu environments with ctrl + alt + shift + F1 (the “back” button) and ctrl + alt + shift + F2 (forward), respectively.

That’s it! Now you can run Ubuntu apps inside of Chrome OS.

Setting up a development environment

The previous section was for setting up an Ubuntu chroot, this section is for setting up some tools that are useful for web development.

Git

You need Git. ‘Nuff said.

1
sudo apt-get install git

Vim with Ruby support

Command-T, a Vim plugin I use, depends on Ruby support. Because of this, I needed to compile Vim with Ruby support enabled. The Ubuntu chroot that Crouton installed lacks a few of the dependencies that a Ruby-enabled Vim requires, so I had to install those myself:

1
sudo apt-get install libncurses5-dev ruby-dev

From here I followed this guide written by Krešimir Bojčić , but here’s the part that actually gets and compiles the source code into an executable:

1
2
3
4
5
6
7
8
9
10
11
12
# Vim is in a Mercurial repository.
sudo apt-get install mercurial

hg clone https://vim.googlecode.com/hg/ ~/vim
cd ~/vim
hg update -C v7-3-154
./configure --with-features=huge  --disable-largefile \
            --enable-perlinterp   --enable-pythoninterp \
            --enable-rubyinterp   --enable-gui=gtk2 \

make
sudo make install

Now your Vim has Ruby support!

OpenSSH

Another critical tool for me is OpenSSH, because I like to SSH into my Ubuntu environment from Chrome and not deal with Unity any more than I have to. The easiest way to do this is to install tasksel and install OpenSSH from there:

1
2
sudo apt-get install tasksel
sudo tasksel

tasksel gives you a UI to select a number of packages you’d like to install, including OpenSSH. You can also easily install a LAMP stack from this UI, if you’d like.

Node

Yup, you can run NodeJS from Chrome OS. It’s as simple as:

1
sudo apt-get install nodejs npm

Full-stack development for $250

The Chromebook is an amazing little device. By running an Ubuntu chroot, you have all the tools you need to build a web project from scratch, and probably a lot more. Keep in mind that it has an ARM instruction set, so some programs may not work (or at least need to be compiled from source). I haven’t had any hangups that I couldn’t fix, however. Why is this worth the trouble? Personally, I just like little computers. It’s also great to have a SSD-powered laptop that has no moving parts - not even a fan. A soft benefit of having such an inexpensive device is the peace of mind of not lugging around a $2000+ laptop with you to the coffee shop. The 11-inch screen is reasonably comfortable to code on and the battery life is great. The Chromebook feels like a poor man’s MacBook Air, and with a full-featured local development environment, I can safely depend on it wherever I go.

In Response to Oscar Godson

My WebKit monoculture post garnered quite a reaction in the community. I figured my opinion would not be particularly popular on this subject, but I stand by what I said. If nothing else it sparked a few really interesting conversations. Oscar Godson wrote a well-reasoned response blog post with some strong counterpoints, which I’d like to address.

Just because something is open source doesn’t mean the downstream browser vendors implement it the same or don’t add to it. If it were true that WebKit was used the exact same away across browsers why are there so many Safari and Chrome differences?

This is true. There is inherent fragmentation in open source, and I don’t know how to solve that problem. However, I would argue that less fragmentation is better than more. Even if a single project gets forked many times and each is heavily modified, there is still a common base from which each fork descends. As I originally said, a world without browser rendering discrepancies is unrealistic. I just think we can somewhat diminish the problem by unifying on a common codebase and branching from it.

All that this does is creates browsers with different versions of WebKit where some have features A, B, C, and some X, Y, Z and some that mix and match and some that implement B differently because they felt that B was implemented in a bad way.

Yes, but this is the nature of open source. This is what happened with Linux, but eventually leading distributions emerged (Ubuntu and Android are examples of market-chosen leaders). Because it’s all Linux it’s not impossible for different versions to cross-pollinate. Ubuntu for Android is a great example of this happening with a degree of success. If either OS was built on top of a different kernel, such a frankenstein would be impossible (or a lot less elegant, anyways).

Also, Gecko is open source, so why WebKit over Gecko?

This much is my own personal opinion. To be clear, the original post reflects my opinion, so take it with a grain of salt. I prefer WebKit to Gecko for a number of reasons. Anecdotally I experience less frustration when developing with WebKit, but (also anecdotally) I am finding WebKit in more places than you can find Gecko. It’s already in two mainstream desktop browsers (Chrome and Safari), it is the (enforced) only option on iOS, and many less-popular browsers already use it or are switching to it. WebKit’s overwhelming market acceptance is why there’s even talk of a WebKit monoculture to begin with. The market is speaking: People want WebKit.

All three of the top browsers will be rapid release soon, so this makes WebKit no different.

True. The update problem will eventually solve itself. I mainly brought up the rapid release cycle to demonstrate how this is not IE6 all over again. My bigger concern is that Web Developers still need to support multiple rendering engines (-webkit, -ms, etc.), which makes us less productive. I feel that the prefix situation is ridiculous and needs to be fixed. The Web Developer community needs to decide which direction to move forward with - I think WebKit is the way to go because it is already winning.

What’s wrong with Gecko and/or Firebug?

Again, this much is my opinion. I feel that Chrome offers more powerful tools than the competition, but developers are of course free to make their own decisions.

And, the fact of the matter is, each WebKit browser has it’s own implementation of the dev tools (see point #1 again). I can’t stand Safari’s. So, you must just mean Chrome’s or do you mean Safari’s? Which is the “right” dev tools for WebKit that are the most “developer-friendly”?

My argument is that WebKit itself is a development tool because it can be scripted for automated tests. I’d bet Gecko has such capabilities, but I haven’t seen a PhantomJS equivalent for Gecko. The community does not seem to support Gecko as strongly as it does WebKit, and I favor options with the best community endorsement when selecting my toolset.

How is Gecko more buggy than WebKit? Are there stats on how many bugs and their severity? Are there more security bugs? Which is safer? I notice more bugs too in Gecko, however, I work in WebKit all day.

I actually agree with this entire part of the counterargument. And no, I don’t have metrics. I was referring to the bugs that a developer experiences during testing, not internal bugs or security issues. Bugginess favors the platform you didn’t start with. I build with WebKit first, and anecdotally I find that a lot of other developers do too. Surely there is a reason for this trend. I would postulate that it’s because a lot of developers have found WebKit and its associated tools to be a better choice in day-to-day development.

In the land of unicorns and rainbows WebKit would be the only browser, innovation would continue, every fork would be a vanilla fork and would somehow work the same on Windows, OS X, Linux, iOS, WP8, and Android. Unfortunately, in the real world that’s not how competition or technology works.

The community need ideals to pursue - this is how we unify. Perfect harmony is unrealistic, but why can’t web development be easier and faster than it is today? I think that it can, and agreeing on a core component such as a rendering engine will get us a little closer to a better ecosystem.

Footnote

I’m not trying to start a revolution. In all likelihood, I’m way off-base with some of my theories, but it is interesting to think about. The WebKit monoculture is something of an elephant in the room for the Web Development community, and I think it’s worth exposing and considering its implications rather than adhering to cultural dogma.

Sit With Your Team

I learned a very important lesson in software development recently. I’ve been on the same team for nearly a year, but for almost that entire time I was not sitting with them. I sat in other parts of the office for various reasons. I was never very far from my team - maybe a 45 second walk. I believed that IM, email, and a multitude of other digital tools would make the distance irrelevant. To be honest, I preferred the distance because it resulted in fewer random flyby interruptions. My logic was, if I always have my headphones on anyways, it shouldn’t matter if I sit with the team, 50 feet away, or at home.

I was wrong.

I recently decided to start sitting in my team’s area. Since doing so, my productivity and overall level of happiness has increased dramatically. All due to a simple change! My teammates are respectful of my need to independently focus with my headphones on, and I of theirs. So what’s different from being across the office? Simply, I can talk to my team now. All I need to do is turn around. The 45 second walk from before encouraged me to not talk to my team and to IM or email them instead, or simply go incommunicado. This led to less collaboration, which led to less fun and less effective problem solving.

This was not something I thought about because the distance seemed trivial. But it wasn’t. Knowing what I do now, I don’t see how working remotely on a regular basis can be effective. All of the best communication tools in the world cannot rival a face-to-face conversation when you are trying to solve a problem. And this is coming from the most introverted person you’re likely to meet.

I Support the WebKit Monoculture

Full disclosure: I work for YouTube, which is owned by Google.

Disclaimer: This post, as well as all posts on this blog, reflect my opinions and not those of my employer.

Counter to the opinion of the Web Development literati, I support a WebKit monoculture. I’ll put this in no uncertain terms: I think the web would be better off if WebKit was the only rendering engine. The common arguments against this are that it’s bad for competition and that “it’s IE6 all over again.” I feel that the former argument is invalid, and the latter is a false dichotomy.

WebKit is open source

One of the core evils behind Internet Explorer is that it is a closed platform. The Web is a fundamentally open platform, and anything “closed” flies in the face of what the Internet stands for. IE attempted to follow in Microsoft’s Embrace, extend, and extinguish strategy, and that is bad for the web.

WebKit is open. The source code is freely available to all, and anyone with a good idea is able to contribute. WebKit has no single owner or controller. In addition to being completely open, it also has strong corporate leadership and support (Apple and Google, among others). WebKit is developed by individuals that want the Web to win, not a single corporation. WebKit is no worse for the Web than Linux is for operating systems.

Rapid release cycle

IE did a lot of good for the Web in the short term, but it left deep scars. It achieved almost complete vendor lock-in that lingers today; many users are stuck in the past because of how difficult it is to upgrade. The WebKit developers recognize this problem and have solved it with easy and frequent updates. In the case of Chrome, it is a fully automatic process. Because WebKit has such strong corporate support, it has faster iterations than any competing project, which leads to more features and bug fixes.

It’s not a platform

To say that a WebKit monoculture is “IE6 all over again” doesn’t really make sense, because WebKit and IE aren’t comparable projects. IE6 tried to be a platform - the thing that apps are built upon - with ActiveX. WebKit is a rendering engine, a single component of many that make up a web browser. WebKit can be implemented into any project that wants to use it.

I don’t love the idea of Web apps that run in only one browser, but I don’t see an issue with apps that support one rendering engine. Focusing on the capabilities of a single rendering engine frees developers up to build great features and not worry about appealing to the lowest common denominator. This freedom is what pushes the Web forward. In a perfect world, you would only only have to write and debug code once. We would be much closer to that reality if all browsers used WebKit for rendering.

It’s more developer-friendly

WebKit has a lot to offer Web Developers. Safari’s built-in developer tools are great, and Chrome’s Developer Tools are simply the best I’ve ever used. These development tools are somewhat orthogonal to WebKit itself - you just usually find them paired with one another. The real beauty of Webkit from a tooling perspective is that it is so flexible. Again, WebKit is a component of a web browser, not a browser in and of itself. PhantomJS is a headless browser that is powered by WebKit. It is fully scriptable and can be used for running automated tests - another thing that substantively pushes the Web forward.

Just as focusing on a single rendering engine allows us to spend more time writing cutting edge features for our apps, it also allows us to build more robust tools. Software fragmentation is bad, and it’s one of the biggest things holding the Web back right now.

Stronger focus on fewer engines

WebKit is not the only open source rendering engine. The big competitor is Gecko, Mozilla’s rendering engine that is used in Firefox. Gecko was instrumental in wresting the Web from Microsoft’s grasp, but it is past its prime. Now Gecko is old, buggy and slow - at least in comparison to WebKit. Imagine if all of the Gecko developers left and joined forces with WebKit? Both projects are (imperfectly) trying to adhere to W3C standards, so fragmentation due to inconsistencies would diminish significantly. Imagine if Firefox switched to WebKit - it would free up a ton of time spent fixing Firefox bugs. Don’t get me wrong, a world without browser-specific bugs is a pipe dream. But standardizing on a single rendering engine would go a long way towards unifying the web.

Competition is good and necessary, but not for all things. I would love to see browser vendors focus on competing on features to benefit the user, not their own interpretation of the W3C standards.