A Tale of Ten Hobbies

The Problem

Over the past two years, I’ve been picking up hobbies left and right. I decide I want to “Get into X”, then buy all the gear necessary to exercise that hobby. Six weeks later, I move on and the hobby becomes a memory. Sometimes I cycle back to old hobbies, hoping to pick up a forgotten skill. As of today, the cycle includes: Figure Drawing, Cartooning, Watercoloring, Tailoring, Piano, Writing, Running, Cycling, Reading, Cooking, and Photography.

When I first noticed this tendency to drop hobbies shortly after picking them up, I dismissed it as a natural consequence of my desire to diversify my life’s experiences, and thus wasn’t something worth fixing. The point was to keep my mind sharp and active, not to get good at a certain hobby.

As I’ve matured though, I’ve realized that that line of logic was a cop-out I used to justify giving up. I never started a hobby expecting to drop it soon afterwards. When I do drop it, I usually do it out of boredom or frustration. Why is that? Why can’t I pick something up and stick to it long-term? Is that even feasible? How would I even fit time into my day for all these hobbies? How good do I really want to get?

After mulling those questions over in my head, I decided that the next time a cycle came about naturally, I’ll ride it through, and I’ll try to take note of what was going through my mind.

Soon after, I picked up photography: Bought the camera and a lens, started shooting, and sure enough 6 weeks later, it hasn’t left my desk in a week. I think I’ve figured out why I drop hobbies, and I have a hunch on how to fix it.

The Realization

Given a creative activity where the output is subjective, judging progress is difficult. Compared to a non-creative activity where the result is clear and progress is obvious, it becomes much harder to find motivation to continue investing time and effort when you don’t see that effort rewarded. For example, you either finish a 50 mile bike ride or you don’t, you either win a game of basketball or you don’t. Contrast that with judging a painting: When are you “finished”? How do you judge its quality?

“Beauty is in the eye of the beholder” is another way of saying that creative works are judged against a personal criteria of taste, quality, and style. As your skill and your exposure to a domain grow, your expectations grow and your tastes develop, but your skill may not grow at the same rate. That’s the case with me. Inevitably, I compare myself to the professionals who have had years of practice, and judge my amateur work against theirs.

Therein lies the problem. When I started photography, merely using a high quality camera with a shallow depth-of-field was enough to meet my expectation of a “good photograph”. However, as I interacted with more photographers, read about photo techniques, had my work critiqued, and refined my taste in photography, I realized that my ability to execute had lagged far behind my expectation. Every photograph became a failure, every photo walk a chore.

Every hobby I’ve picked up has a similar story, except for reading, writing and cycling. I think the feedback loop is so tight in those activities, that any input of effort, has a clear and obvious impact on the output.

This concept isn’t new. In fact, the realization came mostly from reading “Flow”, which I already wrote about in A Moment of Clarity in the Pursuit of Happiness.

The question remains though, what can be done to fix it?

The Solution

I don’t think I can reduce my expectations. I can’t unlearn what makes a good photo, painting, garment, or meal. What I can do however, is set quantifiable and achievable goals. I love cycling because I can measure my performance and compare it against my peers. The competitive challenge drives me and the data-tracking gives me feedback on my progress. Feedback is essential since it justifies my investment of time. Without the feedback, frustration and boredom kick in and I move on

I can set personal challenges that let me operate at the limits of my skill for any of my hobbies. For example, instead of trying to “make a good photo”, I can take an existing photo that I like, and reproduce it. I can set myself a goal of reading a certain number of “favorites” on Flickr. I can decide that I want to make some money from my tailoring.

Those are clear goals that I can work towards. Achieving a goal gives me the positive feedback I need, and increasing the challenge as my skill grow will close off the loop. Eventually, the skill will grow enough with practice to close the gap with my expectations. Until then, I need to put my expectations aside and work towards an achievable goal.

If you’ve ever struggled with the same problem, I hope this works for you, it’s certainly working for me.

The WebKit Inspector

The mobile landscape today is all but monopolized by WebKit, as a result, most of the tooling and infrastructure to support mobile web development on the frontend is taking place in the WebKit Inspector, so I’ll focus on it, and take a deep dive into its entire feature-set and how and when to use it.

Google and the Chrome team have been pumping a ton of resources into the WebKit Inspector. The changes have enabled a whole new class of complex and ambitious applications that would have otherwise collapsed on their own weight. This is great news, of course, but as I talk to more and more web developers about their process and tooling, it became clear to me that many of them haven’t caught up with the changes or aren’t making effective use of the tooling available. This blog post attempts to remedy that, not only by walking you through the inspector’s feature set, but also highlighting certain techniques for bug hunting and feature development that I’ve found to be indispensable. The post is meant to be scannable and shareable. You can click on any header to share a URL to a specific tip/technique or feature to your friends.

Before We Start

Before we start, I want to make it clear that I don’t claim to have infallible knowledge on tooling and process. If you find any of this information to be incorrect, out-of-date, or inefficient, please reach out to me and let me know, I’d love to hear your thoughts.

If you’re new to the inspector or have a passing knowledge of it, do me a favor and play with it as you read this post. Trying things out are the best ways to learn it! “But Majd, I don’t want to keep creating new files and loading them and editing them to test these things out! I have kids to feed!” I hear you, and I agree with you, that’s where the data: URLscheme comes in! 

Try it out: Open a new tab of Chrome, and paste this into the address bar and hit enter:

data:text/html,<b>ZOMG I AM BOLD!?!!?</b>

This is one of the easiest ways to get some HTML into the page and start inspecting it and playing around/investing ideas. Anything after the comma is interpreted as html and once loaded, you can open up the inspector and start playing with it!

One Inspector to Rule Them All

There isn’t a single WebKit Inspector. In fact, there are 5 at any given time that you can use:

  1. Safari Stable
  2. Chrome Stable
  3. WebKit Nightlies
  4. Chromium
  5. Chrome Canary

I’ve tried to sort them from oldest to newest. Chrome Canary gets updated with new features all the time. After they bake for a while with the early adopters, they make their way slowly to Chromium, WebKit Nightlies, Chrome, then Safari. At any given time, Safari’s Inspector is about a year’s worth of development behind Chrome Canary. That is to say, use Chrome Canary for your development.

Getting Set Up

Awesomesauce. You’ve downloaded Chrome Canary, you have it open, you have your site up, you’ve cracked your knuckles and rolled up your sleeves. Hit CMD+J to open up the Inspector or right click on a specific element and click “Inspect Element”.

Now let’s set up the environment so you’re comfortable. The first thing to do is familiarize yourself with the UI. Take a minute to click on every button you see, hover over it to see the tooltip, and find out what everything does.

Dock to Right

The first thing you’ll want to do is click on the gear icon in the bottom right to bring up the settings. Ignoring the horrendously ugly HUDdisplay, I highly recommend checking the “Dock to Right” setting. What this does is stick the inspector to the right side of your window, but keeps it attached. If you decide to pop it out into its own window, then opening multiple inspectors at the same time can become confusing. If you dock it to the bottom, you get a lot of horizontal space, but vertically you’re very constricted. Docking to the right is the best of both worlds. Here’s what it should look like:

Emulate Touch Events

If you’re working on a mobile application, this setting (in the settings HUD) is essential.

Google, if you’re listening: Default the docked setting to “Dock to Right”.

Keyboard Shortcuts

Another quick tip to help speed up your work with the inspector is to get very familiar with the keyboard shortcuts. Go to the Elements Panel (some of the other panels eat the keystroke), and type “?”. This should bring up another horrendously ugly HUD display that contains a list of keyboard shortcuts. The most helpful shortcuts are the ones to navigate the Scripts panel, which we’ll talk about in a bit.

Google, if you’re listening: Make the keyboard shortcuts accessible from the settings panel. Most people don’t know the secret key. While we’re on the topic, why does the HUD have a different light source than the rest of the UI? Why is the border radius so big? Why is the “X” button not vertically centered in the header? Why are some of the shortcuts so small you can’t see them?

Inspecting an iFrame

Debugging iFrames has long eluded web developers. NO MORE! You can now set which iframe the inspector is inspecting through the popup in the bottom center of the inspector that says “”. This panel is interestingly only visible when you have the console expanded (hit escape from any panel).

Google, if you’re listening: Make the iframe drop down accessible everywhere.

The Console

Sweetums. You’re all set up, you’ve cranked up your music, and you’re hacking your heart away. Now you need to actually do something: Run a command, check the output of a function, check for the existence of a method, or see any logs/errors/warnings. This is where console comes in to help. The console is such a badass, in fact, it not only gets its own panel, it’s also accessible from any other panel by hitting the “>=” icon in the bottom left, or by hitting the Escape key.

It also happens to be one of the more intuitive features: Type something, hit enter, see the output of the expression. Any logs are visible chronologically, click the file name on the right and get taken there in the Scripts panel. What you may not have known though, is that you can type multi-line expressions in the console by hitting “shift + enter”. This is really helpful for writing out long commands that involve anonymous functions or complex statements. You can also type “ctrl + L” to clear the console when the logs get overwhelming.

From a DOM-debugging perspective, one of the cooler features of the console is its integration with the Elements panel (which we’ll discuss in the next section). Any element that’s selected in the Elements panel can be quickly accessed using “$0”. That will reference the element and allow you to interact with it. Inversely, whenever you see a DOM node printed in the console, you can right click on it and click “Reveal in Elements Panel” to quickly find it in the DOM.

Google, if you’re listening: Add syntax highlighting to the console command, it’ll help simple parse errors. It wouldn’t hurt to auto-insert braces and parenthesis and quotes, too.

The Elements Panel

So you got you’re all set up and ready to start building your application. The first step is to get your HTML and your CSS looking right (Or JavaScript, depending on your workflow). That’s where the Elements Panel comes in.

DOM Manipulation

The Elements Panel comes into play whenever you are modifying/debugging CSS or the DOM. The main area of the Elements panel is your live DOM hierarchy. As you make changes through JavaScript, you see them reflected live in the Elements Panel. You can use the arrow keys to navigate the hierarchy, and double click on any attribute to edit either the name or the value. You can also click-drag any node in the DOM to reorder it and change its position.

Because its live, I find myself doing a lot of experimentation in this panel. Drag this node here, does it fix that z-index ordering issue? That div is invisible, is it being hidden by another layer?

At the bottom of the inspector, you’ll find a magnifying glass. When you click [that, you can hover over your application itself and it will highlight the node you have selected. This comes in handy when you need a quick way to go to a deeply-nested element.

While you’re playing around with the Elements panel, try right clicking on one of the nodes and see the options that come up. One of these of note, is the “Break on Subtree Modifications” option. When you enable that, any changes that you make to the DOMhierarchy under that node, it will automatically pause, and let you debug it.

CSS Editing

Moving on to the right, the CSS editor is up-there in the list of most-helpful features of the inspector. Superficially, it allows you to live-edit your CSS. However, it reduces the barrier to experimentation so much, I find myself moving things around and playing around with ideas I normally would’ve dismissed as stupid, which is a good thing, as Bret Victor says.

The first thing in the list you see is the “Computed Style” section. Check the “Show inherited” checkbox, and you will see a list of every single style property and its corresponding value that’s applied to the selected node. Even if you didn’t explicitly set a property, it will show you the inherited default. This helps you not only understand what is making up the styling of the node, but it also helps you find out what properties you can set yourself to modify it. Take a quick look at it and see if there are any CSSproperties you didn’t know about, then try them out and see what they do!

Next in the list is the “Styles” section. This shows you the list of properties, grouped by selector, that have been applied to the node. The first sub-section here says “element.style”. This shows the properties set through the style=”” attribute in the HTML. The next section titled “Matched CSS Rules” shows you the selectors that matched the selected node, their properties, and their values, along with the file name and the line number on the right.

To add a new selector, click the “+” button to the right of the “Styles” header, here you can define the selector, hit tab, then start writing properties and values. You’ll notice Chrome offer auto-complete suggestions (this is another great way to investigate which properties you can set). The version of Canary as of this writing requires you to hit the right arrow key to fill in the autocompletion, then you can hit tab to set the value. Hitting tab again will let you set the next property. If you wanted to set a new property to an existing selector, click once on the closing bracket. Clicking on the button to the right of the “+” new selector button will allow you to specify a pseudo selector. Handy!

Colors behave slightly differently. Clicking once on a color value will toggle through a list of representations (hex, rgb, rgba, etc), and clicking on the little colored square will open up the color picker.

All this is great, but let’s say you’ve just spent 10 minutes editingCSS. Now what? How do you save those changes? To do that, click on the file name of the selector (or go to the file yourself in the Resources panel), then right click on the file (which will be updated to reflect those changes), and you can right click to “Save As” and overwrite your existing files. Personally, I find selecting the text and pasting it into my editor to be faster and less error-prone.

One final node on CSS Editing: If you write a new selector (by hitting the “+” key), it won’t persist into a file because it doesn’t know which CSS file to put the selector in.

Google, if you’re listening: Prompt me which file to put a new selector in when I create one. Also, make “tab” fill in the selected auto-completion. Finally, find a way to make persisting changes inCSS to my code easier. This last one is more of a high-level wish, I don’t really know whether or not it’s possible nor how it would work, I just want the process streamlined :P.


Phew, that was a handful! Take a minute to play with all this. When you’re done, let’s move down to the next item in the list: Metrics. If you’re not familiar with the CSS Box Model, take a minute to readthis awesome guide.

The Metrics section basically shows you how the browser is rendering a node from the perspective of content size, padding, border, and margin. Use this tool to debug positioning/dimension problems.

A nice companion tip to the Metrics panel, is that the semi-transparent blue box that overlays the selected node will actually show you the padding and the margin, so you can understand how a box is affecting the flow

Blue is for content, green is for padding, and orange is for margin.

Event Listeners

We’ll skip Properties and DOM Breakpoints for now. I haven’t found a use for the Properties section yet, and DOM Breakpoints shows you any “Break on …” actions you’ve taken by right clicking on a node. The last section we’ll talk about in the Elements panel is the Event Listeners section.

If you’ve attached any event listeners on your node (either using JavaScript or using the attribute in HTML), you’ll find those listeners listed here. This comes in handy when you want to debug whether or not a listener has been properly attached to a node, and what will happen when it gets invoked.

Clicking on the little funnel icon on the right allows you to see either the listeners on the selected node or in the document. This comes in handy if you have listeners attached on things you can’t select in the main list (like window, document, etc).

The Resources Panel

Your HTML and CSS are looking good, and you’ve got a fair bit of JavaScript written to use either the FileSystem API, IndexedDB, LocalStorage, App Cache, or Cookies. The Resources panel is where you go to inspect and debug all these storage resources. Most of them do more or less the the same thing and are pretty self-explanatory: Click a resources, see a list of items, and dig through to navigate your data.

Of note is the first item in the list called “Frames”. It includes a sub-item for every frame in your application, and groups resources such as Images, Scripts, and Stylesheets. Really the only reasons I’ve found to dig through this list is to find a Stylesheet file I edited so I can copy its content and paste it into my editor to save.

The Network Panel

The Network Panel comes in handy when you’re debugging, well, network issues. Is your image asset not updating? The network panel will tell you whether or not it’s being served from a cache. Is your XHR not responding? The network panel will tell you if it’s stuck or error-ing out.

Clicking the “Record” button (the black circle) will maintain a Network session across reloads, handy if you want to see how a change in your codebase affects the network performance.

If you find yourself debugging performance issues, the Network Panel is also very helpful. On the right, you see a “cascading waterfall” of your network requests. If your page is taking a really long time to load, your first step in debugging it would be to look at the waterfall. The blue and red vertical lines show you when the DOMContentLoaded event fired, which means that before then, your use is sitting around waiting for something to happen. You want to reduce that time as much as you can.

The Waterfall

Why do I keep calling it a waterfall, you ask? Well, it looks like one, but more importantly, the reason it looks like a waterfall is because every network interaction takes time both in network latency, and in download time, and the browser can parallelize only so many of them. If your waterfall is wide, you need to go out of your way to cut HTTP requests.

By the way, you can click on the “Timeline” header and you get a drop down (!) to change the sort order. Particularly interesting is the “Latency” sorting, which shows you which of your requests took the longest to establish.

The half-transparent left-side of the capsule shows the latency, and the dark part on the right shows the download time.

The Request Details

On the bottom of the Network panel, click “XHR” to filter the network connections just to XMLHttpRequests. Then click one of them. You see that the right side now changes to show details of that specific request. The first tab shows you all the HTTP Headers sent with the request, and those of the response. This helps when debugging server bugs or CORS bugs.

Preview is a pretty-formatted version of Response. If you’re getting back a lot of JSON, the Preview tab will format it into a collapsable list for you, whereas the Response tab will show it in plain text.

Cookies show you the cookies that were sent as part of the request, and Timing shows more details regarding the time profile of the request. Again, helpful if you have requests taking a long time.

The Scripts Panel

I’m a full-time JavaScript developer, which implies that I spend most of my day in the Scripts Panel. It has also seen some of the biggest changes recently.

Looking around, two buttons worth mentioning are the “Pretty Print” button (looks like a pair of curly braces), which will properly format a minified file. This comes in handy if you get a bug in a third-party minified package and you want to have an even remote chance of figuring out what is going on.

The other button worth mentioning is the “Break on Exception” button (Looks like a pause button). When gray, it’s disabled. Clicking it once will cause your script to pause if it hits any thrown exception. Clicking it again puts it in the “Break on Uncaught Exception” mode, which only pauses your script if you (or something else you use), throw an exception that doesn’t get caught. This is indispensable when you want to track an exception that’s being thrown, since it preserves the call stack and the current state of the application.

File navigation

The addition of tabs in the main workspace and a full file browser, scoped by origin has dramatically improved the efficiency of moving around your project.

To open the file browser, click the weird icon in the top left (it looks like two folders with a right angle between them). By default, the file browser will “float” on top of your workspace, so click the weird icon on the top right of the browser (it looks like a half-white, half-black rectangle) to dock it. Try typing while you’re in the file inspector, it will do a fuzzy-match of the files in your project!

While we’re on the topic of moving around your project, try hitting “CMD+O”, this will open up a TextMate-style “Go-to-File” popover that lets you quickly jump to a file. “CMD + Shift+ O” will open up a “Go-to-Symbol” popover that lets you quickly jump to a symbol in the current file, and “CMD + L” will let you jump to a specific line.

Google, if you’re listening: Add the path to the file in the Go-to-File popover, in case there are duplicates.


Clicking on a line number in the gutter will insert a breakpoint. If your application hits that line during execution, it’ll pause, bring up the Scripts panel, and highlight that line. Then you can inspect the call stack, the scope variables, and inspect/modify your objects. This is the main workflow when debugging issues with your JavaScript.

Occasionally, you’ll want to debug a problem in hot code (code that gets run over and over). Putting a breakpoint here becomes tedious, since you’d have to hit “Continue” over and over. What I usually do in that situation is wrap the function call I want to debug with “window.foo = true” and “window.foo = false”, then right click on the breakpoint, click on “Edit Breakpoint”, then in the textfield I type “window.foo”. What this tells the inspector is that unless window.foo evaluates to true, don’t stop.

So, you’ve added a breakpoint, you refreshed the page, and now your script is paused. Now, the fun begins.

The first thing of interest in the sidebar is “Watched Expressions”. If you care about the value of some expression (Say “MyApp.someController.property === ‘some value’”), then adding that as a watch expression will let you keep an eye on it without having to type it over and over in the console.

Below that, the “Call Stack” section shows you every function call that the system went through to end up where it did. You can navigate this list using “CTRL + .” to go down and “CTRL + ,” to go up in the stack. I usually navigate this list when I care about how a variable came to have its value and how it traveled through the system.

Next, “Scope Variables” lists the local variables and their variables. If you’re using closures to close over variables, then those will be grouped together. The “Global” group shows you every variable on the “window” object (a huge list). As you move through a function, this list gets updated automatically.

Now that you’ve inspected the state of the app on a breakpoint, you’ll probably want to move around. “Continue”, “Step Over”, “Step Into”, and “Step Out” are your friends here. In fact, you’ll be using them so frequently, it’s worth bringing up the keyboard shortcut list again and learning the shortcuts for them. It’s much more efficient to navigate through the list with the keyboard than the mouse. If you’ve used a debugger before, these terms are already familiar to you. For the web developer though, these are new concepts that we didn’t have before.

Continue resumes the execution of the program. If execution hits the same breakpoint again, it’ll pause again. Step over will skip function invocations and stay within the current function. Step into will enter the new function if it’s being called. If you’re calling multiple functions in the same line, you can step into, and out of each one in order. Step Out will leave the current function and go back up one level in the call stack.

These tools are essential in walking through your code and pin-pointing a bug, or finding out which path through your codebase is being followed.

Another handy tool lives under the “XHR Breakpoints” section. As the name suggests, it sets up breakpoints related to XMLHttpRequest objects. The way you specify the breakpoint, is by typing in a substring of the URL you want to inspect. Handy!

By the way, in the “Scope Variables” section, you can right click on a function and choose “Jump to Definition” to jump to the part of the file that defines that function.

The Timeline Panel

Next in the list is the Timeline Panel. As you might have observed, each panel is designed to help debug a certain class of problems: Elements Panel for DOM and CSS, Resources for local storage and assets, Network for HTTP requests, Scripts for Javascript, and Timeline is for browser performance.

What do I mean by “browser performance”? I’m referring to things that are generally out of your control, but which affect the performance of your application. Understanding what’s happening under the hood is essential to supporting the growing complexity of an application.


The first section of interest is the Timelines section. To activate it, hit the Record button (the black circle in the bottom left of the panel). When it’s glowing red, perform a task in your application you like to inspect. If you’re wondering why your scrolling performance is slow, you would try a short scroll. If you’re wondering why loading a modal panel is slow, you would do that. Don’t worry about doing too much and getting overloaded by data in the panel, there are tools to help!

So, you’ve managed to get a nice little timeline of what’s happening, but you’re only interested in a little section of the data. To “Zoom in”, you can click and drag on the timeline graph. You’ll see a couple of draggable thumbs so you can adjust the visible section. Moving down into the waterfall graph, you’ll notice little arrows next to some of the orange capsules. Expand those, and what you’ll see is the function invocation that triggered the browser to do work. In the example below, we can see that a scroll event had fired, invoked a handler, which caused a “Recalculate Style” to fire. If you hover over the item in the sidebar, you see even more detail.

You may be wondering at this point “What are these purple events that are taking up time? Repaint, Recalculate Style, and Layout?”. These are browser-events that are usually invoked by in response to visual changes. For example, If your resize or scroll, the browser needs to do a bunch of work to make sure everything looks as you’d expect it to. You could also invoke these events yourself, so it’s worth understanding what the inspector is telling you and not taking DOM changes for granted.

Recalculate Style

This occurs when you modify CSS properties. In the above screenshot, you see I’m running the same command twice, but seeing different results. The first time I run it, the browser has to Recalculate Style, Layout, and Paint. The next time, it just has to Recalculate style. What’s happening?

Because this is on a fresh page load with nothing visible, giving an unstyle div a height causes its contents to change layout (Layout), causes the visual display to change (Paint), and invalidates the styles (Recalculate Style). The next time I run the same command with the same value, it gets to skip the Paint and the Layout, since they didn’t change. Notice the order: Recalculate Style informs the later processes whether or not they need to get triggered.


Back to our empty page, let’s give our div a width, height, and background color so it actually changes visibly on the screen:

Now, it has to repaint both times, but it only needs to calculate layout once. That’s because the Recalculate Style step found that the positioning/dimensions haven’t changed, but the background has, so it skipped that step. Anything that cause a visual change, causes a repaint.


Often referred to as “Reflows”, a Layout event causes the browser to recalculate the position of elements. For example, say you have a picture that’s floated, so the text wraps around it. If you remove the float, the browser has to “re-flow” the text around it. Paul Irish has a great video where he describes reflows and how to avoid them.

Google, if you’re listening: Please fix the resize behavior. On small Macbook Air screen, it’s common to hit multiple UI bugs when you arrange the inspector/application side by side.

For more detail on how this works under the hood, refer to this blog post.


Now we’ve looked at the timeline, optimized it, but the application is still crashing every now and then after you use it for a while, sometimes it slows down, and it stutters a lot. You’ve seen a few “GC” (Stands for Garbage Collection, which runs every now and then to clean up unused objects) events in your timeline, the Memory tool helps you debug those issues.

Tony Gentilcore has a great writeup on finding and fixing memory leaks, you should definitely give it a read. I’ll give you a quick overview here.

Click on Memory in the sidebar, then click record. Perform a task in your app, and observe the memory profile. Here’s the memory profile for an app that simply creates an object and throws it away every mousemove event:

A typical javascript memory graph looks like a sawtooth function: You keep accumulating memory until the garbage collector runs and cleans up unused memory. A few cycles through GC runs, and your memory profile should be flat. If it’s constantly going up in between GC cycles, then you have a memory leak. As your application gobbles up memory, the app will slow down, and certain browsers (MobileSafari) will actually kill it.

Below the graph you’ll see some more useful metrics to track the number of DOM nodes, and event listeners, they’re pretty self-explanatory.

Finally, let’s say you deployed your app in production, you found a bug in production, located it in the inspector. How do you tell your coworker/developer? Well, instead of taking a static screenshot, you can actually right click on “Timelines” and “Memory”, and save your session so that you can share the actual debug data! Handy when you’re working as part of a team.

The Profiles Panel

So, you’re now at a point in your application’s development where it looks the way you want it to look, HTTP requests are minimized, and you’re causing the browser to do more work than it needs to. Something’s not right though. Everything seems to be snappy, except for one small part. You’ve tried debugging it with the Timeline panel, but it doesn’t give you enough depth and detail. It’s not the browser that’s slow, it’s your own code.

That’s where the Profiles panel comes in.

JavaScript CPU Profiler

The first type of profiling you can do is JS CPU profile. The description outlines at a high level what it measures: What functions your app spends the most time in.

Select it, then click “Start”. Every action you take now, will be logged until you hit the glowing red “Record” button to stop recording (Or click on the “Stop” button). Once stopped, the profiler will show you an ordered list of all the functions that had executed, and the time it spent in each. You’ll probably see something like “(program)” at the top of your list. That’s webkit taking time to do stuff. You can’t inspect it, and you can’t do much about it (but the Timelines tab should help locate some of those bugs!). Apart from that, here’s what a typical profile looks like:

This is the profile for my blog when I open the photo portfolio and open/close a photo a few times. Looks like the most expensive part of that interaction is setting the curtain’s opacity and retrieving the bounding client rect. Just the info I needed to optimize that part of my app.

Google, if you’re listening: There’s a lot of work you can do here to surface useful information and hide useless information. I often get stuck in infinitely-deep lists, or 99.99% of my time spent in (Program), distorting everything else.

CSS Selector Profiler

CSS doesn’t come for free. Complex stylesheets take time to parse, calculate, and apply. The CSS Selector profiler shows you how many times each selector was matched to a DOM node, and how long the browser spends applying those selectors. In a complex application with many divs of the same type, applying styles to them might take a substantial amount of your app’s startup time.

Heap Snapshot

This is one of the most obtuse views in the inspector. So much so, I haven’t actually found it useful. Take this for example:

The amount of useful information there as far as I can discern is zero. I’ll defer once more to Tony Gentilcore’s writeup, may he light your way.

The Audits Panel

We’re almost there! The last panel is the Audits Panel, and it’s basically the last sanity-check of performance you do before going to production. Essentially, it will inspect the resources and the HTTP requests and suggests improvements based on current industry best practices. For example, while writing this, running the Audits panel told me that I should specify the image dimensions in the HTML to make layout faster. Good to know!

All the tips here are well-documented, and you should at least take a quick look through them.


I hope you’ve found at least some of this information useful. I’ve been writing complex web applications on the desktop and mobile for 2 years now, and I’ve had to use each of these panels to solve a different class of problems.

If I’ve mis-interpreted something, missed something, or made any errors, please let me know.

Further Reading

How Browsers Work – A Fantastic, and in-depth look at the processes and plumbing that we build on.

The Mozilla Developer Network Documentation – The most authoritative and up-to-date reference and guided documentation HTMLCSS, and JavaScript. Ignore w3schools.


I’ve been having a recurring thought recently.

The first time was while I was watching A Clockwork Orange when this panning shot came up:

The music, visuals, the characters and storyline came together so well, and everything in the storyline was working together so well, it gave me goosebumps.

The next time that happened was while watching 2001: A Space Odyssey. This shot captured the same feeling:

More recently, a string quartet was playing in the lobby at work. Four musicians moving in perfect synchronicity playing the same thing. It was beautiful.

Above the individual performance though, whether it was a piece of art, a movie, or a musical performance, I realized that what I was admiring wasn’t the piece itself, but everything that must have gone on behind the scenes to bring it all together. Everything complementing everything else, and everything working together. Nothing is superfluous, and everything is there to serve a purpose.

It’s beautiful, and it’s what I try to do with my work.

It’s not easy though, it takes a ton of hard work and practice. It takes patience and perseverance and a self-critical eye to judge your work as you would just other people’s work. To those who have achieved that kind of refinement in their work, I applaud you, and hope to meet you there at some point.

A Moment of Clarity in the Pursuit of Happiness

My eyes squinted, my lips puckered. My palms sweaty and my heartbeat faster. The adrenaline started in my back, tingled my brain, then tickled my toes. It was a moment of clarity: A moment where something obscure suddenly made sense, a moment where the future was laid out for me, waiting for me to realize it. The most recent moment of clarity triggered this blog post.

The realization is that my happiness is something that is in my control to create control, something that I can create for myself and manage. What it means and how it works, are still a little hazy for me, but the idea is there, I feel it in my bones.

I’ve recently started reading Flow by Mihaly Csikszentmihalyi, a book which analyzes years of research into happiness. Here’s the quote that captures the thesis:

What I “discovered” was that happiness is not something that happens. It is not the result of good fortune or random chance. It is not something that money can buy or power command. It does not depend on outside events, but, rather, on how we interpret them. Happiness, in fact, is a condition that must be prepared for, cultivated, and defended privately by each person. People who learn to control inner experience will be able to determine the quality of their lives, which is as close as any of us can come to being happy.

The implication being, the quality of your live (and thus, your happiness), is a choice. It’s something that you decide you want, and something you create for yourself.

Here’s another quote from an article I just recently read called Top five regrets of the dying that supported the same argument:

Many did not realise until the end that happiness is a choice. They had stayed stuck in old patterns and habits. The so-called ‘comfort’ of familiarity overflowed into their emotions, as well as their physical lives. Fear of change had them pretending to others, and to their selves, that they were content, when deep within, they longed to laugh properly and have silliness in their life again.

Steve Jobs also shared a similar sentiment during his famed Stanford speech:

And since then, for the past 33 years, I have looked in the mirror every morning and asked myself, if today were the last day of my life, would I want to do what I am about to do today?

I’m trying to internalize this concept and make it a part of who I am. My identity and my thoughts are my own to have, control, and share. Happiness is a mindset for me to create. I find this newfound control over my life comforting since it means I can stop passing the buck and sulking in any form of unhappiness.

A final thought: On average, you have 78 years total to live. The first 18-20 are spent learning, which leaves 58. Spending 2 years doing something you don’t enjoy is a full 3.4% of your life. What are you getting back for that investment? Money? What are you going to do with that money that will be worth the non-refundable 3.4% of your life? An extra room in your house?

Confidence of the Mobile Web

There seems to be a seeping Napoleon Complex among mobile web devs, it’s almost like they don’t want me to use their web app. I’m sure a lot of developer effort went into building these comfortable, mobile-friendly alternatives to the full desktop experience, so why ruin it by putting up speed bumps between me and the content? (I’ve put example of this below the text.)

If I’m using your mobile web app, it’s because:

  1. I’m not on my own phone, and I’m using a friends’ phone
  2. I tapped on a link in an app
  3. I don’t want to download your app and have it take up a spot on my phone
  4. I didn’t know you had an app and I went to your website by default

The first three use-cases imply that I don’t have an interest in your native app, and the last use-case doesn’t justify trampling on the other three. A simple banner would do. Even better, wait until a user takes an action that’s only available on the native app (like uploading a photo), and then prompt them to download the native app. All around, I see examples of this:

As an alternative, I really like what Instagram does: A simple link that takes you to the App Store. Simple, effective, and unobtrusive.

John Siracusa on Hypercriticism

I came across a 2009 post by John Siracusa called Hypercritical and it inspired me to share some thoughts on the subject. I, like Siracusa, live in perpetual displeasure with my work. I’ve come to attribute this displeasure to the disparity between what my brain wants to create and what my hands can output. I’ve heard Ira Glass tell us that the antidote is practice, so practice I do.

There is a flip side of course, and it was recently summarized by @can:


Seems to me, the only bad criticism is one that is personal and inflammatory. Hyper-criticism is an unapologetic quality, and has a tangible impact on the final product, when channeled properly.

I don’t know how justifiable my criticism is. Is there a threshold of external validation one must meet before their opinion matters? I don’t think so, and I think the more I can constructively criticize – that is, back my criticism with logical analysis – the better I become at judging my own work.

I’m not about to compare my criticism to Steve Jobs’ secret-sauce of sucess (much to my ego’s dismay), but I think the general idea that the key to success is being critical of one’s own work and ” being in a position to demand that it be fixed before a product sees the light of day” is, in fact, a key to Apple’s success and an indication of the failure of many competitors.

Choice quotes from the Siracusa article:

This touches on the idea of practicing even in the face of self-doubt.

But much worse than that, it means that everything you ever create appears to you as an accumulation of defeats. “Here’s where I gave up trying to get that part right and moved on to the next part.” Because at every turn, it’s apparent to you exactly how poorly executed your work-in-progress is, and how far short it will inevitably fall when completed. But surrender you must, at each step of the process, because the alternative is to never complete anything—or to never start at all.

I like what this quote has to say about using criticism to understand not just what sucks, but why it sucks.

And true to form, there was plenty of recursive self-analysis. Do I dislike these new tabs only because they’re different? Are my old habits blinding me to the benefits of this new design? People really dove deep on this thing: generalizing, trying to find the underlying patterns, and changing their positions based on new analyses.

The Broken Pixel Theory


Over the past few months, I’ve started writing blog posts and stopped half-way through, or even worse, I finished them, but thought they weren’t good enough to be posted. Sometimes it’s because I felt like there wasn’t a real call-to-action to the post, other times it’s because I didn’t think the point was well-made. Recently though, I realized that this was causing a writer’s block and the way to unblock myself was to keep writing, regardless of my perception of its quality. “Done is Better than Perfect” and all that. So in the spirit of Ira Glass (See video above), I will practice, practice, practice.

The Broken Pixel Theory

The Broken Window Theory is a fairly well-known criminology theory that correlates the well-maintenance of neighborhoods with lower crime rates. The idea is that a building with a broken window will lower the guilt barrier of breaking another window, which snowballs into a higher crime rate. I stipulate that the theory applies both to application UIs, as well as the code that runs them. A UI with a broken pixel will lower the guilt barrier of breaking another pixel. If unchecked, these broken pixels can snowball to a culture of qualitative indifference.

There are many examples of The Broken Window Theory in daily life. For example, a clean desk tends to stay clean until a piece of paper stays on it for a couple of days. Similarly, I’m much less likely to care about a 2-3 pixel UI bug when the whole UI is a mess. Nobody would care about my bug, and even if they did, they probably won’t notice my bug among the swarm of other bugs.

Sweating the details is important not only from an aesthetic perspective, but also from a cultural perspective. A company’s culture is one of its greatest assets, and its products are a reflexion of it. Apple’s products are polished and smooth, Google’s products are fast and technical, Amazon’s products are simple and frugal. The Broken Window Theory applies not just to the user facing products, but everything internal as well, from the letter head to the internal websites, and all the energy put into maintaining a high level of polish is a worthy investment.

If you thought this blog post was interesting, you may also enjoy Braden Kowitz’s Why you should move that button 3px to the left

How Much Skill Can I Gain in 20 Hours?

tl;dr: Try doing something you’ve always wanted to do for a month. If you like it, you’ll keep doing it, if not, you don’t have to do it for very long.

Play a song, Tailor a pair or shorts

Starting Monday, January 23rd, and until February 24th, I will spend one hour each day either learning to play a piano piece or working on constructing a pair of shorts. I’m thinking three nights on Piano, two on Tailoring.

Here’s the song I will try to learn to play:

Note: The song was “Children Arrive” from the Finding Neverland Soundtrack. It’s been removed from YouTube

I took some piano lessons when I was 10, but I forgot most of what I learned. I still know the very basics of reading music, but I don’t know how to apply them. I know the basics of garment construction, but I still can’t put them together all the way to a final piece. I don’t know if I’ll be able to hit my goal, but it doesn’t matter quite as much as the act of practicing something outside my core competency. If I find that I’m improving, I don’t have to stop in a month. A month is the minimum, not the maximum.


I’ve worked in tech in Silicon Valley for one-and-a-half years. The work is hard, the deadlines are aggressive, and the days are long. I love the challenge, I love the work, and I love the culture, but after a while, I started feeling like parts of my brain were going dormant.

I’m surrounded by people who excel at everything in life from unicycling to writing novels. I draw inspiration from these individuals, and I have a laundry list of activities and hobbies that I would like to be good at, but never found the time or motivation to actually follow through.

The Book

I’m reading The Talent Code Where the author describes the conditions and type of intentional, “deep practice” that breeds greatness. Here are a couple of quotes from the book:

“The trick is to choose a goal just beyond your present abilities; to target the struggle. Thrashing blindly doesn’t help. Reaching does.”

“People at most of the hotbeds [of talent] I visited practiced less than three hours a day. The younger Spartak kids (ages six to eight) practiced a mere three to five hours each week.”

5 hours a week, one hour each weekday, for a month. The experiment is to find out whether one hour a day is enough to meaningfully gain knowledge and skill in an area of interest.

The book has jolted me into a state of restlessness and I want to capitalize on it. I’ll try to describe this “Do something for 30 days” idea, how it has worked for me, and why you should do it as well.

The Epiphany

When I came out to San Francisco in June of 2010, I weighed 240 pounds, and lived a sedentary lifestyle. One of my coworkers convinced me to go running with him one morning. Then he got my ass out of bed early to go for another run later that week, and a couple of weeks later, I found myself looking forward for that morning run. A short conversation and a $50 wager later, I decided to commit to running 2 miles in the morning before work every day for a month.

Here’s the Nike+ graph of that month:

I skipped a few days to rest, and I missed a 5 day stretch because of a trip to NYC.

The epiphany came after the month was done: I kept on running, increased my mileage and eventually participated in a 10 mile run during which I weighed 185 pounds.

I did a similar thing a few months later: I really wanted to read. I felt like there was a lot of knowledge buried in books that I was not exposed to because of my aversion to reading. By the time 2011 was done, I had read 11 books. As I continued reading, my speed got faster, and my vocabulary grew (and I learned a lot!).

The reason I’m recounting this isn’t to pat myself on the back, it’s to highlight the fact that people are in control of their lifestyle and it’s in their power and capability to completely change it. The key is to truly want to do it for yourself. If you decide to do it out of peer pressure, you’re almost certain to fail. I was haggled to lose weight by my family for years, and it wasn’t until I personally wanted to do it, that it happened.

Why a Month is the Perfect Amount of Time

This idea isn’t unique, I can’t remember hearing about it before I did it, but since then, I’ve come across a bunch of people advocating the same thing. Here’s Matt Cutts talking about the exact same idea:


He approached it from a therapeutic perspective. In hindsight, when I started my month challenges, I had just moved to a new city, was still trying to build a social circle, and was feeling a little detached. These challenges fill up your free time, give you a purpose and a goal.

A month is the perfect amount of time for a couple of reasons: First, it’s short enough that if you decide the challenge you embarked on is not fun, you don’t have to do it for long. Secondly, it’s long enough, that if you stick to it, it would form a habit.

If you’re thinking about doing this, the rules are: It has to be something you genuinely want for yourself, and it has to be something sustainable

What do you think? Has there been something you’ve always wanted to do and be good at? What is it? What are you waiting for? Why aren’t you doing it today?

Reflexions on my 24th Year


Last year I wrote one of these and in retrospect, it was too personal. I think at the time, I didn’t expect more than 10 people max to read it. Even though the post makes me feel a bit exposed, it has had a positive effect on me that encouraged me to keep it posted and write another one.

It was around June when I started thinking about where my career was heading and where I was going. I felt like 2010 was such a crazy year, with so much personal and career development, that had I left 2011 as I entered it, I would have wasted a year. I seriously considered what this blog post would say had I stayed where I was. I thought the blog post would be boring and uneventfull, a reflection of what my life would have been. This idea scared me, and made me itch for change.

Coincidentally, a couple of opportunities presented themselves to me at that time, and I considered both heavily. Finally, I decided to join Strobe Inc.. This was my second job out of college, and the freedom that came with working in a startup amazed me, in stark contrast to Apple. On my first day at the job, I was linked to by Gruber (A bucket-list item of mine). Later, five of my blogs posts would make it to the front page of Hacker News (Another bucket-list item), and within 4 months, I released a fewopen source projects. The rush of seeing people use my software and the rush of public-speaking was addictive.

I recommend working at an early-stage startup to any engineer without hesitation. The breadth of knowledge you need to have and the intensity of the work is intoxication. You become a master of your own destiny, your peers become your family. and your work becomes your best friend. Moreover, you end up learning about a topics you wouldn’t otherwise explore: Financing, business developement, operations, etc. – All essential lesson to learn, and all lessons I’m glad I learned.

Fast forward a few months, and I’m now at Facebook. Truth be told, had I been in the open recruiting market, Facebook wouldn’t be the first company I’d reach out to. In hindsight though, I’m etremely grateful for the chance to work here. Regardless of the work itself, I’ve learned a lot about how a large company can operate and how teams can be managed. Again, invaluable life lessons I am grateful to learn.

I now sit in a room with some of the brightest and most accomplished names in Web Development, working on the most popular web destination, on tough problems. My old goal of always being the stupidest person in the room has been handsomely fullfilled.

Life Lessons

Shifting gears to big life lessons learnt, I’d say the biggest lesson is to slow down. I’ve been operating under the time pressure of a race. I felt like every day that didn’t mark a notable improvement in my career was a wasted day. I’ve always been a futurist. I dream about the future, I talk about the future, and I build the future. I couldn’t justify a lack of change, so I enduced change. I’ve come to decide that that was a terrible way to live, and the lesson is that building the future takes time, adjustments, perseverence, and hard work.

Another main lesson I learned it: Fixing what’s broken can be as rewarding as starting over. I’ve always beena “grass is greener on the other side” sort of person, and treat obstacles with dread.

As I enter my mid-20s, I think I’m going to slow down. I want to have a few, but deep and impactful outcomes this year, not a lot of smaller ones. It’s time for me to stop being a student and a consumer and start creating my own world and future.


I’ve met most my SF friends for over two-and-a-half years now. These people have been with me through my weight loss, my job transitions, and my growth over the past couple of years, and they’ve handled all my whining and bad jokes, and I love them for it.

I now live with two of my best friends, in an amazing how in an amazing neighborhood in an amazing city with an amazing job, and an amazing life. I’m extremely grateful and take none of it for granted. As I grow, I want what I have to work for me more than I’ve given it a chance to do in the past. This year will have fewer changes, but bigger outcomes.

I’m excited.

Thoughts on the Kindle Fire

I love Amazon, they’re one of the few companies who like Apple, understand that for a consumer product like a phone/tablet to succeed, it needs an ecosystem to back it, not just the hardware/software to run it. Amazon is also in a unique position of being in charge of one of the biggest ecosystems for media on the planet.

The Good

The focus of the Fire on media consumption through Amazon’s ecosystem is brilliant. The price point (my wild guess is that they’re selling it at a $1-200 loss per sale) is the razor-blade/printer equivalent of tablets. My assumption is that the play that Amazon is trying to earn most of the money on content sales rather than hardware. Assuming a 2 year lifetime, $1-200 is easy to spend on content (especially $10 books and $3-4 movie rentals).

They also cleverly designed the UI to play to the strengths of the Fire. As opposed to the iPad (whose strength is the Apple store) which features apps on the home screen, the Fire features content on the home screen. These sorts of UI decisions influence how people use and perceive the product, and Amazon wants people to know that this is a media consumption device.

The iPad 2 weighs 21.28 ounces, the Kindle Fire weighs 14.6 ounces, this will make a big difference when holding it up for elongated periods of time for reading. I just bought one of the new Kindles (the most basic one) for the sole intended purpose of reading. I’ve never been able to read books on my iPad. The combination of a backlight, the weight, and the screen resolution is a deal-breaker for me. I haven’t played with a Fire, so I don’t know whether or not it suffers from the same resolution/backlighting problems of the iPad for reading, but the weight will help a lot.

The Bad

The 7″ form-factor is an aspect which doesn’t sit well with me. One of the pleasures of using an iPad is the size of the display. Multi-touch gestures are extremely natural and comfortable on the iPad, web content designed for large computer displays feels natural at 10″. The Galaxy Tab 7″ is the only 7 inch tablet I’ve played with, and it felt smack-dab in the middle of being big enough to be comfortable, and small enough to be portable. The difference between the Tab and the Fire though is the same as the difference between the iPad and the Fire: The Fire is intended for serving a smaller subset of use-cases which are less interactive: Reading books, watching movies, listening to music, etc. so it may be less of an issue.

Overall, I think it is a well-rounded product with a string backing ecosystem, I can’t see why this product won’t be a runaway hit. However, I don’t think anyone seriously considering an iPad would opt for a Kindle Fire instead. My hypothesis is that people who were on the edge about spending $500 on a tablet will be much more inclined to buy a Kindle Tablet, which will increase the size of the market, but won’t cannibalize the sales of the iPad.