Safari Extensions: A Primer
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.
Back to our ostrich…
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:
- 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.
- 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.
- Package it up in the extension.
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.
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.
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!
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.
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.