Oh, hello again.

It’s been about two and a half years since I’ve posted here. Such a long time has passed that I’d almost decided it wasn’t worth keeping this blog around anymore. But I’ve had something rattling around in my head for the last month or so, and this seems like the right place to put it. Not today — today is just for catching up — but soon.

As for the catching up, here are some of the things that stand out in my mind from the last two and a half years.

Late in 2011, I moved back to the Apps Script Developer Relations team at Google. Working on the Chrome team was a great experience, but I just couldn’t deny my true and everlasting love for Apps Script.

In October of 2012, I welcomed my second daughter. Now, 18 months later, she and my oldest daughter already have an adorable relationship that both melts my heart and makes laugh at their nonsense every day.

In February of 2013, after 9 years in New York, and after a lot of thinking and talking and even more planning, we moved from Brooklyn back to my hometown of Raleigh, NC. We’ve been here for a bit over a year now, and it’s been fantastic. Looking back now, I can definitely say it was the right move at the right time for us.

In March of 2013, I started a new job as a web analytics engineer at ROI Revolution. It’s a wonderful place to work, and I’ve enjoyed it since day one.

A lot of big things have changed. A lot of little things have changed too. I don’t hate running anymore. I have a car here. We had to explain the concept of having a backyard to my oldest daughter (No, Pa Pa doesn’t have his own park…that’s his backyard. You’re going to have one too!) But most other things have stayed the same. I still have a hard time putting thoughts into words (unless it’s technical documentation, which is just sad). But I plan on posting here again soon, with something that’s geeky, personal, and has been on my mind lately.

Posted in Uncategorized | Leave a comment

Creating Themes for Google Chrome

For the past several weeks I’ve spent time here and there experimenting with creating themes for Chrome. If you haven’t created a theme before, it’s actually really simple. And if you’ve built apps or extensions for the Chrome Web Store, you’ll see that the process is very similar.

I created this HTML5 theme that uses the HTML5 logo and color scheme from the W3C.

New Tab Page screenshot You can see from this screenshot that it’s a very simple theme. The HTML5 logo is in the bottom right-hand corner of the New Tab Page, and there are custom colors or images for the frame around the browser, the area behind the tabs, the tabs themselves, and the text colors.

So, how do you create the theme? Luckily there’s documentation here and here. Some of the information in the wiki is slightly out of date (next on my todo list: update it!), but you will still be able to find the information you need there. Here’s a quick look at the steps I took to make the HTML5 Theme.

First, you need to set up the directory structure. I created a directory named html5theme. Then, inside that directory, I added another called images.
In the html5theme directory, I created a manifest file, called manifest.json. It looks like this:

  "version": "1.0",
  "name": "HTML5 Theme",
  "theme": {
    "images" : {
      "theme_frame" : "images/theme_frame.png",
      "theme_toolbar" : "images/theme_toolbar.png",
      "theme_tab_background" : "images/theme_tab_background.png",
      "theme_ntp_background" : "images/theme_ntp_background.png"
    "colors" : {
      "frame" : [0, 146, 190],
      "toolbar" : [235, 235, 235],
      "tab_background_text" : [115, 115, 115],
      "bookmark_text": [0, 146, 190],
      "ntp_text" : [0, 146, 190],
      "ntp_link" : [0, 146, 190],
      "ntp_section" : [235, 235, 235],
      "control_background" : [235, 235, 235],
      "button_background" : [255, 255, 255]
    "properties" : {
      "ntp_background_alignment" : "bottom right"

The version and name attributes are pretty self-explanatory. In the images section, I specified the images I wanted to use for the frame of the browser and area behind the tabs (just a plain turquoise image), the area that comprises the toolbar and the current tab (a gradient that goes from white to gray), the tabs that are in the background (just a plain gray image), and the New Tab Page background (the HTML5 logo), respectively. All of the images are stored in the images directory. I’ve found that it works best to use .png format for the images, rather than .jpg. The wiki has some helpful tips on recommended image dimensions and what all the different image options are. The colors section details the colors that are used for other elements of the browser window. The colors need to be specified in RGB format, and you can find details on what each color represents here. The last piece is the properties section, and that’s where I’m setting the alignment of the HTML5 logo to the bottom right of the New Tab Page.

After the manifest file and the images are ready, zip those files and upload them to the Developer Dashboard. In the Developer Dashboard, you’ll need to also upload a 128×128 icon and at least one 400×275 screenshot.

Here are a couple things I found helpful while I was learning to create themes:

  • Be sure you look at all the areas of the browser window to make sure your color schemes work everywhere. For example, check that the text in the Bookmarks Bar doesn’t blend in with the bar itself. Check the text color on the New Tab Page too.
  • Install your theme on multiple OSes, if possible, just to make sure it looks nice on all of them. While it should look the same, there might be differences.
  • To test your theme locally before you upload it to the store, type chrome://extensions in the omnibox, expand developer mode and click ‘Load unpacked extension…’. Then navigate to the parent directory for your theme to upload it. That will load your theme in your browser so you can test it out.
Posted in Uncategorized | Tagged , , | 4 Comments

Tutorial and Code for the ‘Building and Publishing Apps for the Chrome Web Store’ I/O BootCamp Lab

I/O BootCamp is an event that takes place the day before Google I/O begins and is filled with beginner-level lectures and labs to get attendees acquainted with Google’s main developer products and platforms. I was really excited to lead a lab at I/O BootCamp this year about building and publishing apps for the Chrome Web Store, along with two awesome TAs, Alex Levich and Kathy Walrath. Unlike the lectures, the labs aren’t recorded, so I’m posting the tutorial and source code for anyone who wasn’t able to attend in person.

The tutorial walks you through the process of building a packaged web app, BootCamp Clock, and publishing it in the Chrome Web Store. It also covers best practices and resources where you can dive deeper and learn more.

Source Code
You can get the source code for the finished app in two ways: by downloading a zip file or on github. The github version also contains the supporting files such as screenshots and promo images that you need for the app listing page.

If you attended the lab in person, I’d like to get your feedback. And if you’re reading along and publish any apps after going through the tutorial, whether it’s an advanced version of BootCamp Clock or something entirely new, please let me know in the comments!

Posted in Uncategorized | Tagged , , , , | Leave a comment

Apps to Bookmarks Bar + omnibox API = <3

Back in March, I posted about the Apps to Bookmarks Bar extension I created, and someone asked in the reviews if it was possible to add existing apps to the bookmarks bar. I’ve been meaning to get around to adding that for a couple weeks now, and finally updated it today.

The new version uses the omnibox API, which basically lets Chrome users turn the omnibox into a command line interface. In this case, you can use it to add bookmark icons for all your currently installed Chrome web apps to your bookmarks bar, just by typing ‘a2b import’ in the omnibox. If you install it and try it out, you’ll see how easy it is. I’m giving you fair warning though — if you don’t want all your installed apps to show up on your bookmarks bar, you probably shouldn’t try it unless you don’t mind deleting them afterwards.

In the manifest.json file, I added a new line to tell the extension that I want to use the omnibox API and what keyword to look out for.

"omnibox": { "keyword" : "a2b" },

Then in a2b.js, I added two new event listeners. The first is for the onInputChanged event, which is fired when a user updates the text in the omnibox and a keyword is active. What I’m doing here is providing a suggestion to type ‘import’ in order to import apps that are already installed as icons in the bookmarks bar.

  function(text, suggest) {
      {content: text + " import", description: "Import your existing apps to the bookmarks bar."}

Next comes the listener for the onInputEntered event. This event gets fired when a user has entered and accepted input for a keyword into the omnibox. The code checks that they entered the word import, and then loops through all the installed apps and adds a bookmark icon for each one to the bookmarks bar.

  function(text) {
    if (text.toLowerCase() == 'import') {
      chrome.management.getAll(function(items) {
        for (var i = 0; i < items.length; i++) {
          if (items[i].isApp) {
	    // Using an id of 1 is a "reasonably safe" way of getting to
	    // the Bookmarks Bar according to http://crbug.com/21330
	    chrome.bookmarks.create({'parentId': '1',
			             'url': items[i].appLaunchUrl}); 				

Posted in Uncategorized | Leave a comment

Launching Apps from your Bookmarks Bar

About a month ago, I met a couple Cr-48 users who were using their Bookmarks Bar as a launcher for their favorite websites and web apps that they’d bookmarked, rather than using the icons for the apps they’d installed on their new tab page. They had removed the title next to each bookmark icon, so there was just a long line of icons across the Bookmarks Bar. I thought it would be convenient to be able launch both your bookmarked websites and apps installed from the Chrome Web Store all from the Bookmarks Bar.

I created a really simple extension called Apps to Bookmarks Bar to do this using the Bookmarks and Management APIs that are part of the Chrome Extensions framework.

Let’s take a look at how it’s made. First, every extension needs a manifest.

  "name": "Apps to Bookmark Bar",
  "version": "0.1",
  "description": "Adds an icon to the bookmark bar when you install an app from the Chrome Web Store.",
  "background_page": "a2b.html",
  "permissions": ["management", "bookmarks"],
  "icons": { "16": "a2b16.png",
             "48": "a2b48.png",
             "128": "a2b128.png"}

The parts that are most important here are the permissions and background_page sections. In the permissions section, we need to specify “management” and “bookmarks” so the extension can use those two APIs.  The Management API is used for interacting with the list of apps and extensions that a user has installed, and the Bookmarks API is used for interacting with a user’s bookmarks. We’ll look at how this extension is using both of those APIs in a little bit.

In the background_page section of the manifest, we’re specifying the name of an HTML file, “a2b.html”.  A background page is an HTML file that runs in the extensions process and exists for the lifetime of the extension. In this case, we’re just using it to hold our script for adding apps to the Bookmarks Bar.

Here’s what a2b.html looks like.

<!DOCTYPE html>
  <script src="a2b.js"></script>

It’s just including a script, which is doing the interesting (though still pretty simple) stuff.

chrome.management.onInstalled.addListener(function(info) {
  var id;
  if (info.isApp) {
    // Using an id of 1 is a "reasonably safe" way of getting to
    // the Bookmarks Bar according to http://crbug.com/21330
    chrome.bookmarks.create({'parentId': '1',
                             'url': info.appLaunchUrl });

This script adds a listener for the onInstalled event. That means it will execute any time an app or extension is installed. But we’re only concerned with apps, so then we check to see if the event was triggered by an app.

The next line is actually the part that took the longest to figure out. I wanted to be able to locate the “Bookmarks Bar” folder within the BookmarkTreeNode objects that are returned from getTree(). It ended up being trickier than I expected to find a clean way of doing this. At first I thought I’d just look for a node whose title was “Bookmarks Bar,” and that worked on a Mac, but on Windows, it’s actually “Bookmarks bar.” It would be easy enough to work around that, but what if the browser’s language settings were set to something other than English? So I looked for another approach, and I came across this feature request. The feature request acknowledges that there’s not a simple way of finding the Bookmarks Bar folder, but that it’s reasonably safe to rely upon the Bookmarks Bar folder having the id of 1,  so that’s what I’m doing. Using chrome.bookmarks.create, we’re creating a new bookmark in the Bookmarks Bar, with the app’s launch URL as the bookmark URL. We’re not specifying any title for the bookmark, so it will just show up as an icon. The icon will actually just be the generic one until you visit the app, and then it will use the favicon.

So that’s it! I may try to expand on this to have an option to also create bookmarks for apps you’d installed prior to installing the extension, and possibly to handle cases where you disable or uninstall an app.  All the code is also on GitHub, so you’ll be able to find any updates there too.

Posted in Uncategorized | Tagged , , | Leave a comment

Chrome hackathon recap

On February 19, I had the opportunity to speak at a Chrome hackathon in Cambridge that was organized by the Mass GTUG and sponsored by HubSpot and General Catalyst. The materials for the tutorial I led on building a packaged app are posted here. Jason Glasgow, an engineer from the Cambridge Google office also gave a talk on Chromium OS.

About 50 developers attended the event, and 11 apps and extensions were demoed at the end of the day. I was impressed to see so many people stay the whole time, working right up until the end. The two demo teams that got the most votes each got a Cr-48.

Clutter, built by Victor Costan and Ying Yin lets you browse multiple websites in a single tab. This can be a really useful extension for Chrome OS users.

Demo of the Clutter extension

Katherine Fang and Wolfe Styke built a sidebar extension for List.it, where you can add or delete notes and search.

Demo for list.it extension

Some of the other demos were:

  • A todo extension that parses tasks from a text file and displays them with a nice and motivational UI.
  • A Google Analytics extension to view data overlaid on your website.
  • An enhanced version of the countdown app that moved 3D shapes as the timer counted down.
  • Automato, an extension for streamlining workflows.
  • Etherpads, an extension that helps you keep track of etherpads that you’ve visited.
  • A Chrome Web Store app for texwith.me.
  • A packaged app version of GWT Tetris.
  • Newstube, an extension that pulls in YouTube videos related to headings from pages you visit and displays them in a cool, radial view.
  • A hosted app to display a social wallboard.
Posted in Uncategorized | Tagged , | Leave a comment

Let’s get this party started

I’ve had this domain for over a year now. I’ve been going back and forth in my head about what I wanted to do with it, and as a result haven’t done anything at all. Here’s a picture of a cat to tide you over until the party actually starts.

Posted in Uncategorized | Leave a comment