Ostrich Pt. II: Intricate & Delicate

Hey! It's me!

Ostrich Pt. II: Intricate & Delicate

Posted on August 16th 2010

Ostrich is a special piece of technology. For me, it’s ahead of its time, at least concerning Safari Extensions. It’s pretty unusual to build something so intricately complex on a rather simple platform. In short, Ostrich is made of Javascript, HTML, CSS and WebSocket. It’s an app.

Safari Extensions: A Primer

The Safari Extensions Platform is mainly a way to augment the browser experience with small additions written in HTML/CSS and Javascript.

As explained here, Safari Extensions have a “back-end” in Javascript which is loaded only once per Safari application session and should contain the heavy-lifting of the extension. The “front-end” is comprised of injected javascripts (before or after page load) and injected stylesheets which are appended to every page. The back-end and front-end communicate through a simple message/proxy system. They both have access to a variety (but not the same) of functions pertaining to the browser, the window and the tabs, to either set or get some values.

The intended purpose, in my view, is to extend the browser’s capabilities with additional functionalities like a reload button, a statusbar with more info à la Chrome, various toolbar buttons (Gmail, Google Reader, Instapaper), change the style of specific websites, etc. All small(ish) additions to make life easier on some tasks. I especially use the Gmail, GReader and Instapaper extensions, as they achieve a simple purpose in a more elegant way than greasemonkey scripts or bookmarklets.

Up to now, that’s pretty much how it’s been used. Some use it more creatively by appending interfaces on websites, but most just go with 20% of the effort for 80% result. They usually don’t go beyond.

You can follow pretty much all the new extensions coming in (the ones not featured in the Extensions Gallery) on the Safari Extensions Tumblog.

Back to our ostrich…

The Front-End

Ostrich needs an interface. As a UX Designer, that’s definitely a top priority. The interface is the first thing I did. Not even as an extension, but as a static prototype using StaticMatic, HAML and SASS.

The process of creating Ostrich’s interface goes as follow:

  1. Create a sound structure with very unique IDs and classes (you don’t want to interfere with or be interfered by any website’s styles.) I used HAML.
  2. Style the interface with CSS3 and some of webkit’s goodies. Appending !important to everything you style is crucial, else the website could interfere. I used SASS and Compass.
  3. Package it up in the extension.

I’m hosting the template on a server because sometimes I need to make changes only to the template and not the extension. So everytime Ostrich loads, the template is fetched. It would be fairly easy to store it as a string (albeit, a big one) with Javascript and server it whenever the inject script needs it.

CSS can give you quite a headache here. I tested Ostrich on hundreds of websites (mostly by using it myself) and modified the CSS constantly to make it look pretty much the same on every website. Painstaking but worth it. Luckily there is an update system in place, so I can ship smaller patches for the CSS from time to time.

The Back-End

Most of Ostrich’s processing is done in the back-end. It’s written entirely in Javascript. I used JQuery at first, but at some point it didn’t allow me to easily write decent Object Oriented JS anymore.

I might have refactored the whole codebase about 3 times. Now it’s rolling on MooTools which feels way more adapted to organizing your code better. It’s fully evented too, I’m proud of that bit. MooTools is a great JS library, I plan on using it on all my future projects. I fell in love with it.

During the last refactor (the biggest one), I also abstracted most of the code in order to create a Safari Extension App Framework. I’m going to release this one soon(ish) when it gains more maturity, I don’t think it’s ready yet though. It’ll be open-source too.

The Server

There’s only one reason for needing a server to operate Ostrich. There are no decent Javascrip library to use OAuth. Oh yea, there is one, but there’s so few documentation and I’m probably too much of a newbie to use it, it just doesn’t make much sense to me.

So instead, I used a small Sinatra application to handle the connection to Twitter, retrieving tweets of all sorts and sending them. I used the twitter_oauth gem at first. It proved to be resource-heavy and crashed a super powerful server all the time if there were something like 100 active users (probably less though). After a lot of downtime, a lot of support from people loving and following @ostrichapp and a lot of help from various ruby devs over IRC and such, I was able to rewrite the server to handle Twitter in an asynchronous manner. The new architecture permitted any number of connections. It still crashes about once every 1.5 days, but it’s not related to the server load.

Tweets are now retrieved within an EventMachine and sent through a WebSocket connection every Ostrich client initiates. WebSocket is a sweet sweet technology, I’ve been meaning to use it for a long time and I’m not disappointed. The challenge is recuperating the connection once the server crashes, whenever someone loses his wifi or whenever someone puts his Macbook Pro to sleep. I’m working on it and pretty much have a solution that’ll be rolled out in Ostrich 0.3!

Delicate Technology

As you may understand now, Ostrich is not only a Safari Extension, it’s a complex system delivering UX sweetness. Relying on so many parts makes Ostrich super easy to be instantly unusable by everyone if any one of them doesn’t work right. For now though, I don’t think there are any other ways to handle a real app within Safari Extensions.

The main pain point has been the server. Ruby is not my forte, I’ve been coding it as an intermediary programmer for years now, but this is out of my league. Consider the server programming and maintenance taking about 80% of my time. The front-end is a joy-ride when I can get to it.

In The End, I Learned A Lot

One of the things I would love to do in life is being a CTO in a cool startup. Since I never could have sold myself as a CTO with my portfolio or my experience, I had to do it by myself. I finally felt I could do it and Ostrich seemed like the right challenge at the time.

It proved way more difficult than expected. That pleases me. Had I created a boring an easy app, I wouldn’t have learned much. During the development process, I went from a “front-end javascript coder” to something else entirely, I now see how apps can be created as a whole with Javascript. I polished my HTML/CSS skills in the process, though I’ve reached some kind of plateau lately.

As of my Ruby programming skills, that’s a whole different story. I never had to create something so intricate in the past. I learned so much from people over IRC who kindly helped me for free. The Interactive Ruby Console (IRB) is a wonderful tool I learned to love too, it’s as much of value now to my Ruby as is the Safari Inspector to my CSS & JS. I could go on forever, it’s been a wonderful learning adventure.

For those wondering why I’m emphasizing so much on learning, you should read some of my previous posts about why I do what I do. I’m autodidactic and learning is my passion. Ostrich is my own assignment as a business and web development endeavour. Building it is the current latest most difficult task I’ve had to do and therefore I am surpassing myself.

I surpass myself therefore I learn.

Discussion