YUI App Theme

Tonight I pushed a new project to GitHub called yui-app-theme. It’s a generic, skinnable layout designed for web applications — particularly admin areas — built using YUI Grids.

In other words, it’s a starting point.

Usually when doing freelance work for clients, unless you’re building on top of an existing CMS like WordPress or MiaCMS, you’ll have to create an admin area for the client to login and manage their site. Or maybe you’re building a bug tracker or some other web application. Whatever the situation, yui-app-theme provides a solid foundation to start your work.

It offers a tabbed layout with many of the common UI elements that web apps need. Content blocks, tabbed modules, one and two-column forms, error messages, etc. But most importantly it’s built using YUI Grids so it’s semantically structured, cross-browser, and easy to extend. You can radically alter the layout with just a few quick changes. Try clicking through the layout options on the demo page.

YUI App Theme preview

I’ve done my best to keep things logical and easy to use. Here’s a quick example of how to use and extend the built-in content blocks.

A basic content block, or module, is created with the following markup

<div class="block">
    <div class="hd">
        <h2>Your Header Content</h2>
    </div>
    <div class="bd">
        <p>Your body content goes here.</p>
    </div>
</div>

You have a containing div with a class name of block surrounding two inner divs, which make up the head and body content of the block. In the browser you’ll see

YUI App Theme content block preview

Content blocks resize to fit their surroundings. That means you can take the same markup used for a body content block and move it into a sidebar — the block will automatically shrink to fit the smaller space.

We can also extend the block to have a tabbed appearance. To do this, we just need to add an extra tabs class and define our tabs using a <ul>.

<div class="block tabs">
    <div class="hd">
        <ul>
            <li class="active"><a href="#">Tab 1</a></li>
            <li><a href="#">Tab 2</a></li>
            <li><a href="#">Tab 3</a></li>
        </ul>
        <div class="clear"></div>
    </div>
    <div class="bd">
        <p>Your body content goes here.</p>
    </div>
</div>
YUI App Theme content block with tabs preview

Easy.

However, you’ll notice than by using an unordered list to build our tabs, we had to remove the <h2> tag. In some situations we may want to keep that header around for SEO purposes — visible to search engines but hidden from users. yui-app-theme handles this situation automatically by hiding any <h2> and <h3> tags inside a content block’s header. (Technically, it applies an extreme negative left margin to move it outside the browser window.)

Let’s take this example one step further and change the appearance of the tabs by making them look separated. All we have to do is add a spaces class to the content block.

<div class="block tabs spaces">
    <div class="hd">
        <ul>
            <li class="active"><a href="#">Tab 1</a></li>
            <li><a href="#">Tab 2</a></li>
            <li><a href="#">Tab 3</a></li>
        </ul>
        <div class="clear"></div>
    </div>
    <div class="bd">
        <p>Your body content goes here.</p>
    </div>
</div>

And we get

YUI App Theme content block with separated tabs preview

It’s that simple. With the right CSS, minor HTML edits can create powerful changes when rendered.

If you explore the demo you’ll see that applies to the page layout as well. You can very quickly change the color scheme or page width. And even adjust the sidebar, move it to the opposite side, or switch the layout to a single column. It’s all possible because yui-app-theme, itself, is built on top of a solid foundation — YUI.

I’ve already started using this template in my own projects and found it incredibly helpful to have my application layout up and running so quickly. I hope you can benefit from it, too. And, please, feel free to fork yui-app-theme on GitHub and contribute your own improvements.

PHP Wrapper for Yahoo! GeoPlanet

Earlier this month I wrote a quick PHP wrapper for Yahoo!’s GeoPlanet API. It’s a super useful service for querying geographical information about nearly any place on earth — addresses, landmarks, colloquial locations, etc. Or, as the official description says

GeoPlanet helps bridge the gap between the real and virtual worlds by providing an open, permanent, and intelligent infrastructure for geo-referencing data on the Internet.

There were already Perl, Python, and Ruby wrappers. I figured I’d throw PHP into the mix.

Pete Warden has already written some example code that uses the wrapper to emulate Twitter’s nearby location search.

You can download the source from GitHub. As usual, it’s licensed under the MIT License and free to use in any way you like.

Serving Static Content on Amazon S3 with s3up

I’ve written twice about using Amazon S3 to host your website’s static content. It’s a great solution for small websites without access to a real content delivery network. And now that Amazon has launched CloudFront on top of S3, it’s even better.

But there are still ways we can improve the performance. The trick is to upload our files using custom headers so they’re served back with a proper expiration date and gzipped when possible — i.e., the techniques recommended by YSlow.

I’ve written a command line tool which simplifies this process called s3up. The idea is simple. It uploads a single file to S3, sets a far future expiration date, gzips the content, and versions the file by combining the filename with a timestamp. Each of these actions are optional and can be controlled via the command line.

The basic syntax:

s3up myS3bucket js/somefile.js somefile.js

would upload a local JavaScript file named somefile.js into your Amazon S3 bucket named myS3bucket inside the js folder.

We can build on this command by adding the -x flag, which tells s3up to set a far future expiration header. By default, it chooses a date ten years in the future:

s3up -x myS3bucket js/somefile.js somefile.js

This lets the browser know to keep the file cached indefinitely.

Passing the -z flag uploads two copies of the file. One normally, and a second that is gzipped and renamed filename.gz.extension. You can then dynamically serve the compressed version to browsers that support it.

Finally, the -t flag uploads and renames the file filename.YYYYmmddHHmmss.extension. This lets you easily create versioned files when you need to update an existing file. (You need to use a new filename since the browser was told earlier to always load from the cache.)

Combining all three options we get:

s3up -txz myS3bucket js/somefile.js somefile.js

This uploads your file, compresses it, sets the correct expiration date, and versions the filename — all in one easy step.

If you’d prefer to choose your own string for versioning, you can specify it with the --version flag:

s3up -txz --version=v2 myS3bucket js/somefile.js somefile.js

In that example, the file would be stored in S3 as somefilev2.js.

s3up also echoes the new filename so you can quickly paste it into your HTML. If you’re on a Mac, you can automatically copy the new name onto your clipboard by piping s3up to the pbcopy command.

If you’d like to take this a step further and integrate s3up into your existing deploy scripts, you can leave off the filename argument and instead pipe the data to upload via stdin. So, if you’re using another tool like the YUI Compressor or byuic, you can run:

somecommand | s3up -txz myS3bucket js/somefile.js | pbcopy

Uploading Multiple Files

A common task is uploading a whole folder of images. You can do this in one step by appending a slash (/) to the S3 filename and using wildcards to specify multiple local files. Example:

s3up myS3bucket images/ /path/to/your/images/*.jpg

When s3up sees images/ ending with a slash, it treats it like a directory and stores all of your files into it. Make sure you remember the slash on images/. That’s what triggers the special “directory” mode uploading.

Download

You can grab the latest copy of s3up from the its GitHub project.

Download All of Your Flickr Photos and Sets

iLife ’09 was released today. And with it came a much improved version of iPhoto with facial recognition, geotagging, and Flickr and Facebook support. With so many new ways to slice and dice my photos, I wanted to start over with a clean slate and get everything organized in iPhoto before re-exporting my library back to Flickr or wherever.

Before I could do that, I had to download all of my photos out of Flickr so I could import them into iPhoto. I wanted something simple that would also retain my photos in their correct sets when downloading. I found one program for Windows, but nothing for Mac. (Did I missing something obvious?)

So here’s a simple PHP script that uses the phpFlickr library to download all of your photos. It creates a folder for each set plus an extra one for photos not in a set. This grabs your original, full-size photos — both public and private.

You can get the script from my Google Code project here. You’ll also need to download and include a copy of the phpFlickr source from here.

Sync Your Adium Chat Logs With Dropbox

Here’s a handy trick that will let you sync your Adium chat logs across multiple Macs using Dropbox. From a command line, cd into your Dropbox folder

cd ~/Dropbox

and then

ln -s ~/Library/Application\ Support/Adium\ 2.0/Users/Default/Logs "Adium Logs"

That will create a symlink from your Dropbox folder to your Adium log directory. When syncing, Dropbox will follow this link and process your chat logs as if they were stored inside your Dropbox folder.

Do this on each Mac you want to sync. I have two Macs at home and another at work — it’s worked like a charm so far. But, be sure to backup your chat logs the first time you do this just in case something goes wrong.

Use Rapache to Manage Virtual Hosts on Ubuntu

For people who like the idea of VirtualHostX but want to setup virtual hosts on Ubuntu rather than Mac OS X, Stefano Forenza has created the Rapache project. Like VHX, Rapache is a GUI to manage Apache virtual hosts. With just a few clicks you can create a new host and the appropriate DNS settings for local development.

Rapache Project

Forward Your Growl Notifications to Twitter

I’ve got three Macs that I regularly use. One at work, a laptop for personal use, and a Mac Mini connected to our living room TV. I use Growl on all three — it’s so ingrained in my workflow (IM notifications, new emails, background tasks) that I often forget it’s not a part of OS X.

Keeping track of notifications on your local machine is easy — they just appear — but for computers in another room (or timezone even) it becomes trickier. Growl has support for sending notifications over a network (I’ve written some PHP code to send them), but they don’t work beyond your LAN unless you want to mess with firewalls and changing IP addresses.

While that can work if setup correctly, it can be somewhat annoying. It doesn’t matter if you have broadband packages from o2 or any other ISP, it’ll still cause headaches in the end. Luckily, with a little help from Twitter, we can route around these problems.

For a long time I’ve wanted a way to receive Growl messages from any of my machines no matter where I am. A few months back I even created a (now aborted) fork of Growl that integrated with Amazon’s Simple Queue Service. It worked ok, but it was kludgy and not something that the average Mac user would want to spend time configuring.

Last night it dawned on me that Twitter was exactly the sort of distributed notification system that I was looking for. All I needed was a way to forward my Growl notifications to a Twitter account. (Or tweet them as all the cool kids say.) I did some Googling and found lots of people using Growl to show new tweets but nothing that would go the opposite direction.

So, I sat down and began looking through the source for Growl’s display plugin protocol. Two cans of Red Bull and four hours later, I saw my first Growl message appear in my Twitter timeline.

How Does It Work

Simple. Download this Growl plugin, unzip it, and double-click to install. You should then see a new style called “Twitter” under the “Display Options” in Growl.

Just fill in your Twitter username and password. You can also choose a prefix that will be added to the front of each tweet (@username for example).

A Few Examples

Growl is super customizable. You could set Twitter to be your default display style, but that would be too noisy. A better solution would be to set only certain apps to send notifications via Twitter — or only specific messages within those apps.

For example, I use my Mac Mini to download torrents using Transmission, which supports Growl. I configured Growl to tweet whenever a download completes.

My Mac at work does a full SuperDuper backup each night. I configured it to tweet whenever a backup fails.

Both of my parents have MacBooks. Even though we’re 3,000 miles apart, it’s still my job to keep them running smoothly. I setup nightly cron jobs on their machines which check for low disk space, pending Apple software updates, and other maintenance tasks that they might not think to check. Any problems are growled and posted to Twitter.

Final Thoughts

I’ve setup each Mac to send its Growl notifications to its own Twitter account. That keeps the notifications separate between machines. Then, I protect their updates (I don’t want strangers viewing my growl logs), and subscribe to them via my primary Twitter account. All of the tweets from each machine appear in my timeline.

And that’s when the power of Twitter really shines — because those updates are portable.

I can view them on the web, on my phone, I can subscribe to them via RSS, have them sent to my phone as SMS messages, or mix and mash them using any one of the many Twitter add-on services. You could even use Yahoo! Pipes to filter the messages.

My point is that by sending your Growl messages to Twitter, you’ve suddenly freed up a ton of data that had been stuck on your local machine and combined it into a portable format you can take anywhere.

Thanks to Matt Gemmell for MGTwitterEngine which does the Twitter heavy lifting in this plugin.

Download

Download Growl Twitter.

Amazon S3 Improvements in PHP-AWS

Two and a half years ago I began working with Amazon Web Services — first with S3 and then SQS and EC2. The code was eventually cleaned up and released as an open source project called PHP-AWS. Since then, it has remained relatively unchanged. Just bug fixes and the occasional support for new AWS features when users contribute patches. It’s not particularly pretty, but it has stood up well against time. The S3 class was recommended by Raymond Yee in his book Pro Web 2.0 Mashups, and a number of people have emailed examples of production sites where the library is being used.

Still, the biggest drawback (particularly with the S3 class) was that the curl commands were piped to the shell — they didn’t use PHP’s native curl extension. This was done to bypass PHP’s memory limits to allow large file uploads (and also because we didn’t have time to find a workaround). It was a dirty hack, plain and simple.

But, today, the S3 class redeems itself with full support for PHP’s curl extension. Not only do large file uploads work (I just tested a 1.5GB disk image), but there is support for new S3 features like query string authentication and copying objects.

As this is a complete rewrite, I consider it a beta release — user beware. I’ve converted over all of my own code to use the new class, which has given it a good bit of testing. It’s stable enough for my purposes, but I don’t want anyone to be surprised if there’s a bug or three lurking about.

Download the code, kick the tires, and please report any bugs you find.

Parse Command Line Arguments in PHP

This afternoon I needed an easy way to upload files to Amazon S3 and set specific headers on them. I’ve built one-off scripts like this in the past, but this time I wanted to generalize the problem into a reusable shell command.

I pulled in some code from PHP-AWS and got it working fairly quickly. However, I got swamped with an ugly nest of if and switch statements when I began adding support for multiple arguments and switches. A quick Google search didn’t find any ready-made PHP solutions, so I rolled my own.

It’s a small class — about 60 lines. It could easily be turned into a single function instead, but I like using classes as ad-hoc namespaces. Anyway, it’s fairly robust for a twenty minute solution. Here are a few examples of the syntax it supports.

cmd -a -b -c // Single letter flags

cmd -abc // Same as above

Beyond setting a few flags, you can also assign values to those flags.

cmd -a foobar.jpg -bc

In this case, b and c are set just like the previous example. And a is set to the value foobar.jpg as you’d expect.

Double-dash, long names are also supported.

cmd --some-flag
cmd --another-flag=charlie // You can use an equal sign
cmd --another-flag charlie // Or not. It's up to you.

And those can be mixed with the single dash variants.

cmd -ab --bigflag=foo -c bar apricot orange

So, a and b are set. bigflag is set to “foo” and c is set to “bar”. “apricot” and “orange” will appear as arguments not associated with any specific flag.

My point is that you can use nearly any standard Unix convention.

So, given that last example, here’s how you’d parse it using the PHP class.

<?PHP
    $args = new Args();

    if($args->flag('a'))
        // -a was set, so do something

    if($args->flag('bigflag') == 'foo')
        // --bigflag was set to 'foo'

    foreach($args->args as $arg)
        // Do something with each argument.
        // Args will be bar, apricot, and orange.

So that’s it. The class doesn’t assume much. It just picks out what you give it. It’s up to you, the programmer, to interpret those results.

As always, the code is released under the MIT License and available here.

How to Stream Your iTunes Music Over the Internet

Update: Want to stream your iTunes music over the internet? Try Highwire! It streams your iTunes library and a whole lot more 🙂

I keep all of my iTunes music stored on a Drobo attached to an Airport at home. This frees up valuable space on my laptop and lets me listen to it via Front Row on my TV as well. It’s a much more convenient solution all around.

The only problem is that I lose access to my music when I’m on the road or at work. I’ve seen other services or 3rd party apps that let you stream your music online. They work well enough, but I’ve always thought it silly to pay for a feature that iTunes used to have. In honor of iTunes’ new 8.0 release this morning, here’s my simple workaround.

First off, you’ll need a Mac at home with iTunes open that is always connected to the net. In my case, that’s a Mac Mini in our living room. It also needs to have “Remote Login” (ssh) enabled in System Preferences → Sharing.

Then, poke a hole in your router’s firewall to that machine on TCP port 3689. Here’s a screenshot of my router’s settings:

(Note: your computer’s IP address might be different than mine.)

Then, with that done, anytime you want to listen to your music elsewhere, run these two commands in Terminal on the Mac you’re listening with — not your Mac at home.

ssh your_username@your-home-ip-address -N -f -L 3689:your-home-ip-address:3689

That creates a tunnel from port 3689 on your local machine to port 3689 on your Mac at home. (That’s why you needed to open the hole in your firewall.)

mDNSProxyResponderPosix 127.0.0.1 squeal "My Music" _daap._tcp. 3689 &

That creates an iTunes Bonjour broadcast notification locally which points back to your Mac at home. In other words, it tricks your copy of iTunes into thinking there’s a Mac nearby sharing its iTunes library. When iTunes tries to connect, the traffic is automatically rerouted to your other Mac.

Sidenote: if you don’t have the mDNSProxyResponderPosix command installed on your Mac, I have download links at the bottom of this post.

So that’s it. No need for third party software. When you open iTunes, you should see your music library appear in the “Shared” section of the sidebar. (Much to my excitement, the newly announced Genius playlists appear as well!) You can close the Terminal window once you’ve connected to your music library. (The mDNSProxyResponder command needs to stay active until then.)

Making it Better

To speed things up a bit, I’d put those two command into a shell script and place it in your ~/Library/Scripts folder. I call mine music-tunnel. That way, you can run that one command and have everything up and running automatically.

Or, if you’re feeling adventurous, you could wrap the whole thing inside a simple Cocoa app with a nice On / Off button. But that’s a project for another day…

Downloading mDNSProxyResponderPosix

Here’s a binary download of the mDNSProxyResponderPosix command for Intel. Place it somewhere in your path. And here’s the source if you’d like to compile it yourself for PowerPC.