Creating Bluebird Themes

Matt Patenaude (Updated 4/14/2009)

Creating themes for Bluebird is easy: all you need is a bit of knowledge of HTML and CSS. For the most part, JavaScript knowledge is not necessary unless you want to do something really crazy with your theme.

Bluebird utilizes the powerful WebKit engine, the same one that powers Safari and Dashboard. As a result, anything you could do on a Safari web page, you can do in a Bluebird theme. In fact, all you need to do to create a Bluebird theme is create a web page, a special Info.plist file, and put it all in a folder with the .bbtheme extension.

Getting Started

To get started, create a folder for your theme. It is recommended that this folder share your theme’s name, and required that it have the extension “bbtheme” (for example, the theme named “Torn Paper” is contained in a folder called Torn Paper.bbtheme). If you have Bluebird installed, this folder should automatically become a “package”, or a folder that’s trained to act as a single file. To get into it from here, Control + Click it, and select “Show Package Contents”. Alternatively, you can just remove the “.bbtheme” extension until you’re ready to test it.

Theme Location

When Bluebird launches, it searches three places for themes:

You should never place your own themes in the internal themes directory, and only sparingly use the System Application Support directory (for themes that you want accessible to every user on your system). That leaves us with the User Application Support directory, so we’ll move our theme there for now.

Info.plist

Bluebird themes contain metadata in an Info.plist file, the de facto standard for OS X package metadata. Info.plist is a property list file, which is simply an XML file using Apple’s Property List syntax. If you have the Developer tools (ie, Xcode) installed, you already have an application on your system called Property List Editor, which you can use to help you create these files.

If you don’t have this application, you can create one in any text editor — the basic syntax is shown below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>BBMainFile</key>
    <string>index.html</string>
</dict>
</plist>

Creating Your Theme

Your theme will be comprised of a combination of HTML, CSS, and MGTemplateEngine instructions, along with a little bit of JavaScript to facilitate the loading of new tweets. Information on MGTemplateEngine can be found in the package, available at Matt Gemmell’s Cocoa Source website. The basics, however, are available here.

First, design your theme as you would design any normal HTML website. The fun starts when you adapt it for use with Bluebird. There are two primary types of statements that you will use when building your template: syntax statements, and output statements. Command statements look like this, and serve some sort of language functional purpose:

{% for tweet in tweets %}

Output statements look like this, and are replaced by the value of what they contain:

{{tweet.author.fullName}}

The body of your tweets will be contained within an HTML file called tweet.html (and optionally dm.html to include a custom template for direct messages). Within your main template file, you then use a for loop, to loop over the global tweets array, and print out the rendered HTML for each. IE,

{% for tweet in tweets %}
    {{tweet.html}}
{% /for %}

… would go in your main template file, and

<div class="tweet">
    {{tweet.content}}
</div>

… would go in a file called tweet.html.

The above snippet would loop over all the tweets, printing a div containing the content of each one. You can use conditionals like in most languages with the if statement. For instance, this is how you might conditionally assign the class of a tweet:

<div class="tweet {% if tweet.isOwn %}self{% else %}{% if tweet.type == BBReply %}reply{% /if %}{% /if %}">
    If this is by me, it has the class "self"... if it's a reply,
    it has the class "reply".
</div>

Once your theme is designed, you’ll need to add some very basic JavaScript to your theme to allow Bluebird to update the tweets. You will have to implement three JavaScript functions (samples are provided):

<script type="text/javascript">
function $(el) { return document.getElementById(el); }
function addTweet(theTweet, shouldDisplay, nextTweet, isNew, tweetObj)
{
    if (!shouldDisplay)
        theTweet.style.display = 'none';

    $('container').insertBefore(theTweet, nextTweet);
}
function removeTweet(theTweet)
{
    $('container').removeChild(theTweet);
}
function changeVisibility(theTweet, shouldDisplay)
{
    theTweet.style.display = (shouldDisplay) ? '' : 'none';
}
</script>

Note that the above snippet assumes that the tweets are contained within an HTML element with an ID of “container” (this can be anything, including a div or a ul); it also defines the common JavaScript function $() for convenience (this is defined for you by many popular JavaScript libraries, like Prototype). These functions should not require modification (except for changing instances of “container” to the ID of your actual tweet-containing element), but you can modify them to add funky things like animation of new tweets, etc.

The last thing you’ll need to do is setup your theme to notify Bluebird when it’s time to load the list of tweets. This is done by calling the Bluebird.loadTweets() JavaScript method once your page has loaded. Typically, you’ll just want to insert it into your body’s onload attribute like so:

<body onload="Bluebird.loadTweets();">
<!-- Blah blah blah -->
</body>

And voila! That’s all there is to it. You should also note that, if you do want to do anything funky with JavaScript and need to debug, you’re provided with a function called Bluebird.log(), which outputs whatever you pass it to the Console.

For more information, look through the provided themes, they should give you all the information you need.

Theme API

The Theme API is what you will use to get your theme to interact with Bluebird properly. For this, three mechanisms are provided for you: a set of keys in your Info.plist file, an API exposed to MGTemplateEngine, and a special bluebird:// URL scheme. (As a note, Bluebird also responds to twitter:// URLs of the same format, but you should only ever use bluebird:// within the application to ensure that another Twitter client does not attempt to handle your requests).

Info.plist Keys

MGTemplateEngine API

Execution in a theme begins at a top level, with the tweets array.

From your main template, you iterate over the set of tweets, printing the HTML content of each tweet as it’s encountered with the tweet.html command.

Each object in the tweets array (referred to here as tweet) then has a certain set of properties you can use.

In addition to the properties outlined above, each tweet object also has an author property, which is an object of type Person. Each Person also has a select number of properties that you can use. Note that, for direct messages, a recipient property of type Person is also provided; it matches the author property exactly in syntax.

bluebird:// URL Scheme

Classes Assigned by Bluebird

Bluebird assigns some standard CSS classes to HTML it inserts into the content of tweets.

JavaScript Interaction

The specifics and exact syntax of the necessary JavaScript functions and their implementation is detailed in the document A New Theme Format for Bluebird.

Sample Project

A sample project will be provided with a future build of Bluebird. However, one is not currently available.