Jekyll Static Website on Google Cloud Storage

Google Cloud Storage and Jekyll

Years ago, we built websites by hand editing HTML files and FTPing them to our web server. It was painful. Content management systems like WordPress and Joomla! made authoring content easier, but with them came hosting complexity and scaling challenges. Nobody wants their site to go down on its most popular day.

Enter Jekyll. It's like we've come full circle. Jekyll is a framework for generating static HTML sites. It combines the productivity of templating and markdown syntax with the simple hosting of hand edited HTML.

This blog entry goes through setting up, a Jekyll static website, on Google Cloud Storage. It also covers scripting updates.

Why Google Cloud Storage?

Jekyll outputs HTML, which you can host pretty much anywhere. You could blow the dust off of your WS_FTP CD-ROM and upload it to your ole' web server, but there are much better options these days.

You could use GitHub pages, Firebase Hosting, Divshot, or many others. This blog post isn't meant to be a hosting provider comparison, but here are some cool things about Cloud Storage to keep in mind:

  • Zero configuration consistent, fast delivery from global edge caches
  • Do you have a static website with terabytes of rarely accessed content? Nearline storage could save you a ton of money
  • Scales to really, really huge static websites, like many terabytes
  • Fine grained access control to individual objects
  • Do you upload a lot of video from mobile connections? The REST API has neat features like chunked multipart upload of big objects.

In any case, it doesn't take long to try out a hosting provider. So, evaluate a few, and pick the one that fits your needs best. In the mean time, let's get up on Cloud Storage.


Verify your domain and set up DNS

Before we can create a Cloud Storage bucket for, we need to prove to Google that we own the domain. Do this from Google Webmaster Tools. There are many ways to verify your domain. Here we'll use the DNS method because is a brand new domain name.

  1. Log into webmaster tools with the same account you plan to use for Cloud Storage.
  2. Click 'Add Property' and type in your domain name.

    add property

  3. Select the 'Alternate methods' tab, 'Domain name provider', and then 'Other'

    select dns

  4. Add the provided TXT record to your domain name and give it a few minutes to update.

  5. Since we're already editing DNS settings, take the opportunity to add a CNAME alias that points to

  6. Return to webmaster tools and click 'Verify'.

Set up a static website bucket on Google Cloud Storage

  1. Sign up for Google Cloud Platform, if you haven't already. The form asks for a credit card, but don't sweat it. Cloud Platform won't automatically bill you; the credit card is just verify your identity. Also, new accounts get a $300 free trial. This is plenty of credit to determine if Cloud Storage is right for your project.
  2. Go to the Google Developers Console and click 'Create Project'.
  3. From the project page, use the left side menu to navigate through Storage -> Cloud Storage -> Browser, and click the blue 'Create bucket' button.

    Create bucket

  4. Return to the bucket list and click the bucket menu. Edit default object permissions and grant allUsers read access. This makes everything we add to the bucket publicly readable by default.

    make public

  5. Click the bucket menu again, but this time select 'Edit website configuration'. Set the 'Main page' to index.html and save.

Your bucket is all set up to serve a website. Time to put some stuff in there.

Initial deployment and test

Use the drag and drop features of the developer console to make the first deployment. This is an easy way to verify that everything is set up correctly.

  1. Build your Jekyll site

    $  jekyll build
    Configuration file: /Users/mimming/
            Source: /Users/mimming/
       Destination: /Users/mimming/
    Auto-regeneration: disabled. Use --watch to enable.

  2. Browse to your bucket on the developer console and into drag the contents of \_site on to the page.

    drag and drop to deploy

  3. Once the upload finishes, visit the website.

  4. Celebrate a successful initial deployment.

Automate deployments

It's cool that you can drag files on to the bucket browser, but we're real developers. We want something we can automate. This is where scripting uploads with the Cloud SDK comes in handy. We could hack up a quick shell script, or integrate it with a build system like gulp.

Shell Script

  1. Install the Cloud SDK using the instructions for your platform.
  2. Authenticate your SDK

    $ gcloud auth login

  3. Use gsutil to upload your content. It has a bunch of commands, but stick with rsync for now.

    # -m use faster multithreaded uploads
    # -d delete remote files that aren't in the source
    # -r recurse into source subdirectories
    $ gsutil -m rsync -d -r . gs://

  4. Wrap these commands in a tiny shell script. I call mine

    jekyll build &&
    gsutil -m rsync -d -r ./_site gs://

  5. Run, see changes go up to the cloud, and celebrate the upload of another dinosaur picture.


Some of us are build system hipsters. If you're cringing at the thought of a directory of utility shell scripts, you're probably already using gulp.js to build your Jekyll site. If you're not, you should channel your node.js mojo and check it out.

It turns out that gulp.js plays well with the Cloud SDK. Add a deploy task to your gulpfile.js:

var gulp = require('gulp');

gulp.task('deploy', function() {
  var spawn = require('child_process').spawn;   
  var jekyll = spawn('jekyll', ['build'], {stdio: 'inherit'});

  jekyll.on('exit', function(code) { 
    if(code === 0) {
      require('child_process').spawn('gsutil',  ['-m', 'rsync', '-r', '-d',
'./_site', 'gs://'], {stdio: 'inherit'});
    } else {
       process.stdout.write("Build failed. Exit code: " + code);

Run gulp deploy. See more changes go up. Celebrate a world with even more dinosaur pictures.

Note: The weird callback thing is in there because we're chaining child processes. It tells gulp to wait for Jekyll to exit successfully before attempting to push to Cloud Storage. You can learn more about this pattern in the gulp.js reference docs.


And just like that another dinosaur themed blog is on the Internet, and this one is backed by Cloud Storage. You created a bucket, configured it to serve public web traffic, and uploaded content. Then you crafted some scripts to make publishing updates easier. And, you celebrated dinosaurs a little along the way.

If you have questions or comments, please tweet at me =]

Google Glass and the Twiddler 3

Glass, now with a Twiddler and VimTouch

Update: Greg Priest-Dorman tipped me off about an issue with these instructions. XE12 has a bug that causes keys to repeat if you type quickly. I'm quite slow on my Twiddler, but I was able to reproduce it with this command:

$  adb shell input text "abcdefghijklmnopqrstuvwxyz-0123456789"

Which yields this

repeated keys on XE12

Greg reports that XE8 works well, but downgrading that far is tricky. I'm going to experiment with flashing earlier versions and update this post with my findings.

Voice commands are perfect for commands, but something I've always dreamed of doing on Google Glass is taking notes. The Twiddler 3 seems like the perfect input device, and we all know that the best text input software is Vim.

Getting all of these to work together took a little bit of hacking. This blog entry guides you through the process of pairing Glass with the Twiddler 3, and using it to type your first words into VimTouch on Glass.

Here's a summary of what's involved:

  • Root and downgrade to XE12
  • Disable automatic updates
  • Pair your Twiddler 3
  • Install and run VimTouch

Warning: This tutorial includes steps that will void your Google Glass warranty. Proceed at your own risk. If you accidentally brick your Glass, don't complain to me! :)

Root and downgrade to XE12

Current versions of the Glass operating system such as XE22 do not pair with Bluetooth HID devices like the Twiddler. However, older versions that were based on Android 4.0 Ice Cream Sandwich do play well with them. Before we can pair Glass with the Twiddler we need to downgrade to XE12 and disable automatic system updates.

Download XE12

Why are we downgrading to XE12? Because it was the highest version based on Ice Cream Sandwich. It has the most features and bug fixes included. You can also use XE10 or XE11, if you prefer.

All of the boot loaders and system images for Glass are available from the System and Kernel Downloads page in the official Glass documentation. Scroll down past the warnings and download and boot.img.

glass system image downloads

Root and downgrade

Now the scary part: flash the rooted bootloader and downgrade to XE12. This is the step that voids your warranty and could brick your Glass. It also erases any data on Glass, so download your photos and video before flashing.

The instructions for flashing these images to Glass is on the very same page. Run these commands using the adb and fastboot tools included with the Android SDK. These instructions work best from Linux, so flash from there if possible.

Note If you're flashing from a Mac, Glass might crash after each fastboot flash command. If this happens, take a deep breath, power cycle Glass, and use adb reboot bootloader to get back into fastboot. Proceed to the next image.

# enter fastboot mode 
$ adb reboot bootloader            

# verify Glass is in fastboot
$ fastboot devices 

# acknowledge the warning
$ fastboot oem unlock
# actually unlock the bootloader
$ fastboot oem unlock

# flash the rooted bootloader
$ fastboot flash boot boot.img     

# flash partitions with factory images
$ fastboot flash system system.img
$ fastboot flash recovery recovery.img

# reboot into normal mode
$ fastboot reboot

Your Glass is now running XE12. You should see the XE12 log in screen.

Don't log in yet. You need to disable updates first.

Disable automatic updates

Once you log in, Glass automatically updates to the latest version. You don't want this, so we need to disable updates. Unfortunately, we need adb access to disable updates. You can work around this, but it requires some silly tricks, and an wifi network that you can disable quickly.

  1. Set up a temporary wifi network. I used the portable hotspot feature of my mobile phone.
  2. Use the Glass setup page to log in to your account. Once you're logged in immediately disable your wifi network.
  3. Swipe to Settings -> Device Info. Enable USB debugging (adb).
  4. Delete GlassUpdate.apk to disable automatic updates, and restart Glass.
$ adb root

# delete the automatic update app 
$ adb shell rm /system/app/GlassUpdate.apk

# see if Glass already started updating
$ adb shell ls -al /cache
-rw-r--r-- app_5    app_5     5416530 2015-05-24 23:33
drwxrwx--- root     root              1969-12-31 16:00 lost+found

# if it is, delete the zip
$ adb shell rm /cache/

# reboot to kill any remaining running processes
$ adb reboot

Automatic updates are now disabled. You can add your primary wifi network to Glass.

Note: This is a pretty aggressive way to disable updates. I tried other techniques, like disable, but nothing else I tried persisted across restarts. If you figure out a better option, please let me know.

Pair your Twiddler 3 with Glass

Pair the twiddler

The built-in Glass settings software does not know how to pair with Bluetooth HID devices, but HY and PY from the Glass team showed us how to do this in the Hacking Glass session at Google I/O in 2013.

  1. Get your a copy of Settings.apk. You can build it from source or download a binary from a trustworthy source.
  2. Side load Settings.apk and fire off an intent to start it up.

    $ adb install ./Settings.apk
    $ adb shell am start -S

  3. Turn on your Twiddler, and reset Bluetooth pairing with the special chord N+S ROOO.

  4. Awkwardly use the touchpad to move around the settings app. Go to Bluetooth, scroll down to the Twiddler, and tap to pair. If you get stuck for some reason, use adb input keyevent to simulate arrow key movement.

Fix the settings card

broken settings card

At this point, you may notice that the settings card is broken. You have two apps that respond to the settings intent, but the intent chooser is broken in XE12. To work around this, you can install an alternative launcher like Mike DiGiovanni's Launchy. Follow these steps to install it.

  1. Check out Launchy. It won't build out of the box. It depends on a bunch of XE16 GDK stuff, which does not work on your XE12 device.
  2. Edit, and remove all of the code that refers to any class in the package.
  3. Build the apk, and side load it on to your Glass.

You can now tap through the Glass main menu to start Launchy, and Launchy can start Glass' default settings app.

Install and run VimTouch

vim on glass

At this point we have a Glass running XE12 with a paired keyboard, but none of the built in software responds to text input from a keyboard. To make your Twiddler useful on Glass, you need a keyboard friendly app. What better app to install than the Android variant of Vim?

Clone VimTouch, build it from source, and install it on your Glass.

It runs great, and you can verify your keyboard input right away. It also shows up in Launchy, so you can start it that way in the future.


Is your Glass still working? Great! You've rooted it, downgraded it, disabled automatic updates, and typed characters into the best text editor in the world. Congrats!

But the story isn't over yet. Launching VimTouch from the touchpad is a little bit clunky, and the Glass home app starts each time Glass wakes up. It's not a useful note taking device yet. We need a way make a sticky text editor that continues across sleep cycles, and a way to launch apps from the Twiddler.

I've worked out solutions for both of these, but they're a story for another blog post. If you're interested in a writeup, please tweet at me.

A faster way to copy your Raspberry Pi SD cards on OS X

A Raspberry Pi with some SD cards

The Raspberry Pi is awesome. One of the reasons that it's awesome is because it's so newbie friendly, and has great docs. For example, it has a great guide on creating an SD card image from OS X.

But, that guide does have one problem. The way they tell you to use the dd tool results in a very slow copy.

Default Instructions

Here's what happened when I followed the instructions to install Raspbian on a cheap SD 16 GB SD card.

mimming@femputer:~$  sudo dd bs=1m if=2015-05-05-raspbian-wheezy.img of=/dev/disk2
Password: correcthorsebatterystaple

3125+0 records in
3125+0 records out
3276800000 bytes transferred in 2903.165983 secs (1128698 bytes/sec)

2903 seconds? That's like 48 minutes. That's almost an hour! But, but, but I want to be hacking sooner than that.

Targeting rdisk

Luckily there's another way! OS X provides /dev/rdisk#. The r stands for raw and provides a more direct interface with the SD card. In this case, more direct = more faster.

mimming@femputer:~$ sudo dd bs=1m if=2015-05-05-raspbian-wheezy.img of=/dev/rdisk2
Password: correcthorsebatterystaple

3125+0 records in
3125+0 records out
3276800000 bytes transferred in 652.856126 secs (5019176 bytes/sec)

The same copy took just over 10 minutes. Not too shabby.

Bigger Chunks

Some Stack Overflow answers indicated that using bigger chunks might speed things up even more. I gave it a try.

mimming@femputer:~$  sudo dd bs=10m if=2015-05-05-raspbian-wheezy.img of=/dev/disk2
Password: correcthorsebatterystaple

312+1 records in
312+1 records out
3276800000 bytes transferred in 653.281030 secs (5015912 bytes/sec)

The result is almost exactly the same. It seems that block size does not matter too much.

A tip about dd progress

While dd is a neat tool, it's hardly verbose. Sometimes it's hard to tell if it's working hard, or if the process is hung (which can happen if your computer goes to sleep).

You can query it for a status update by pressing CTRL + T.

Thanks to that goes to this superuser answer.

A Twiddler 3 review

A Twiddler 3


The Twiddler 3 is the most flexible single-handed wireless input device that I have ever used. It has some rough edges, and it requires significant time investment to learn, but it's worth it.

What's a Twiddler 3?

It's a handheld chorded keyboard. Instead of pressing down on a single key to make a letter, on a Twiddler you lift multiple keys to make a letter (or sequence of letters).

The Twiddler 3 works as a USB or Bluetooth keyboard. It's targeted at use for mobile devices and wearables.

Unboxing and first moments

The box contains the Twiddler 3 keyboard, a velcro strap, and a MicroUSB cable. I didn't take any photos, but there are already unboxing videos on YouTube.

After flipping that little switch to power it up, mine started looking for a device to pair with. I was mashing the keys and typing gibberish into my laptop within a minute of opening the box. The unboxing experience is great.

This is where the polish starts to end, and the mildly rough road begins.

Pairing with other stuff

The next thing I wanted to do was verify that the Twiddler could pair with all of my tiny computers. You know, the mobile phone kind. This was when I realized that the box didn't contain any printed instructions. A quick web search turned up the official docs. They're a bit disorganized and hard to read, but after a few minutes of clicking around I learned that I could clear the paired state with the special chord N+S R000.

It paired easily with my Moto X, 2013 Nexus 7, and iPhone 6+. It did not pair as easily with
Google Glass, but that's a story for another day. (Literally another day: I'm drafting a follow up blog post about using the Twiddler 3 with Glass right now.)

Holding it correctly

This may seem like a no-brainer, but my instincts lead me astray here. Initially I grabbed it with my right hand and tightened the velcro band. The docs have detailed guidance about how to hold the Twiddler. The tl;dr: is to hold it with your non-dominant hand, and leave the velcro band pretty loose.

The recommended grip wasn't very comfortable for me, so I swapped out the velcro for a strip of elastic and gripped it with my thumb.

how Jenny holds her Twiddler

Hacking Layouts

Twiddler Tuner

One of the coolest things about the Twiddler 3 is how configurable it is. The layout is easily programmable with the tuner web app.

Don't be afraid to experiment with your layout right away. Your layout is a very personal choice. Lots of people like the default one, espiecally those who type with their left hand, but I found it difficult to learn and uncomfortable.

Try these popular layouts.

If none of those work for you, write your own. I did.

Actually using it to type stuff

Expect to invest a lot of time in being productive. Research indicates that you'll probably get pretty fast, but expect to practice, a lot.

There's a tutor web app. It works OK, but I gave up on it for a few reasons.

  • Your progress is only saved in a cookie, which is easily lost. You can export your progress, but oddly, you can't import it.
  • It only supports the default layout.
  • It does not work on mobile.

Instead, I learned from lots of short practice sessions:

After a couple weeks, I got up to about 20 wpm.

Most important

I know what you're really wondering, can it type emoji? Can I use a single chord to (╯°□°)╯︵ ┻━┻?

Well, no. The tuner does not approve of table flipping. It gets all scrambled when you save it.

(╯°□°)╯︵ ┻━┻

And it might be moot, because I've been told that the Twiddler itself may have trouble flipping tables... something to do with the HID spec. Anyway, if I figure out a way to hack around it, I'll post a follow up.

In conclusion

Becoming awesome with it is hard, but it's worth it.

Oh, and if you get lonely, drop by the Google+ Wearable Computing community. It seems to be the best place to talk about general purpose werable computing, and input devices like the Twiddler.

SaferRoads @ the AT&T Mobile Hackathon

SaferRoads - yes, we have a marketing site

I love hackathons. I like running them. I like volunteering at them. I also love hacking at them. There's nothing quite like spending a weekend hacking out some code with new friends.

This past weekend I attended a hackathon hosted by AT&T at their office in Palo Alto. This was the third AT&T Palo Alto hackathon that I've attended. They're great events.

  • They hit the sweet spot on size: 100 to 200 hackers
  • Great diversity in turn out: people of all experience levels and backgrounds.
  • I can always find a great, friendly pick up group.
  • The Foundry space has a great mix of small rooms, couches, and standing desks to work on.
  • The wifi works the whole time.
  • The organizers are a pleasure to hack with.

As a side note, despite attending three of their hackathons, I don't really understand the AT&T developer program. Most of their APIs require a paid premium developer account, and they don't have a feature set that that's very hackable anyway. Yet, this mystery does not detract from their events.


Somehow I convinced a group of 6 awesome people that it was a good idea to work on the project at the top of my to do list: A way to tattle on Uber drivers illegally parking in my bike lane. We named it SaferRoads.

After a day of hacking with the Myo, the YouTube Data APIs, and Android, we got something working:

interface for next version

No, that's not really it. That's a mock of the UI that we didn't have time to implement. The real app has an engineering interface that does not look nearly as nice. But, we achieved a lot.

  • It is indeed possible to write an Android app overnight, but only barely.
  • The YouTube Data APIs are kind of tricky to use from Android.
  • The Myo is really fussy, to the point of being useless beyond technical demos.
  • I registered my first alternative TLD domain name!

We also made a couple shameful achievements

  • We checked a hard-coded OAuth refresh token into a public GitHub Repo (yes, it's already disabled)
  • We used an InVision mock as part of our demo

You can read more on the marketing website or see the shameful code on the GitHub repo.

Until next time, happy hacking everyone :)