August 15, 2012

Four is the magic number

Bloc Party are back from hiatus [1] and are preparing to release their fourth record, appropriately titled “Four,” next week on August 20th. In addition to this being the band’s fourth release, it also represents them getting back to their musical roots, as it was only the four of them in the studio. Listen to the lead single “Octopus” to hear what I mean.

This theme of simplicity is carried onto how the record is represented visually as well. The cover displays four olympic colored rings on a black background. Within the linear notes you’ll find four similarly colored images of each band member, leaving us to believe that the rings must represent each of the members.

Oh, and a quick aside while I’m on the topic of visuals: both the band logo and linear notes are set in default web fonts! I guess their logo was always set in “Gill Sans,” but the italicized “Georgia” within really takes the cake. This band was built for the web.

So… the number “Four,” simplicity, colored circles, hued band photos, and default web typography… how could I turn these parameters into an interactive and accessible album premiere? And, how could users become part of the theme themselves while simultaneously increasing the viral reach?

What if while in the premiere, users were able to personalize their “Four” experience by grouping themselves and three of their closest friends into their own four ? And what if this personalized version was sent to those friends in the form of a dynamically generated composite photo and post?

I think this story is much more meaningful than a “retweet” or “like” AND a lot more fun. People like to click on stories about themselves, and if you perhaps included a tagged colorized image of that friend in the post… oh, they’ll click it alright.

In addition to the interactive twist, this app also needed to cover several basic goals and features:

Simple, multi-device, responsive audio player

Clear player controls for playing and seeking

An introduction covering the record theme and app instructions

Links for purchasing the album

Buttons to share the experience socially

And perhaps a way to explore the lyrics

I knew early on that this was going to be too much content to jam into a single page’s height and width, especially when thinking about iOS devices, so I decided to design a longer layout than usual.

After spending some time sketching out several different layouts, I found the answer right in the theme and divided the site into four sections:

Intro - provides a nice introduction about the band and record

Interactive - contains the four “editor”

Exploration - a long list of track titles and lyrics

Outro - credits related to the recording of the album

Given the length of layout, now four times longer than what I typically build, I wanted to include an interesting way to navigate between these sections. I found a jQuery plugin called Curtain.JS written by Victor Coulon that animated between site sections by using a curtain-like reveal method. For example, the intro section would pull up, like a curtain, to uncover the Interactive section. Pretty rad.

Finally, I established a central column of content around 300 pixels wide in anticipation for a responsive mobile layout. Mobile First!

I love designing within the constraints of minimal assets, because you can always find interesting ways to stretch things out. In fact, I find it much more rewarding to expand on an album’s aesthetic vision rather than complying one-to-one with the base assets.

I started by using the four band member photos to establish background textures for each section by desaturating, blurring, and brightening || darkening them depending on where they fell within the layout. This gave me a nice base to focus on more clean typographic design for the majority of the site. Did someone say Georgia italic?

I used a combination of SASS and Compass to establish some sophisticated cross-browser mixins that could generate both the ringed logo circles and user avatar circles. Check out this logo example:

@mixin center($size) left: $size top: $size @mixin square($size) height: $size width: $size @mixin circles($size, #border, $spacing, $color) @include inline-block() @include square($size) position: relative li @include border-radius(100%) background-position: center center background-size: cover border: $border solid $color position: absolute @for $i from 0 through 5 li:nth-child(#{ $i + 1 }) @include center($spacing * $i / 2) @include square($size - $spacing * $i)

All the social and player buttons were created using Symbolset’s excellent hybrid typeface meets iconography meets OpenType semantic symbol font. Just go fucking buy it already.

By far, the most difficult UI piece to figure out was the Four editor. I actually printed out paper templates that only contained the ringed circles in the middle of a stark page, and didn’t allow myself to take a break until I was onto something. Which is probably not the best idea… but I was lucky enough to have a major breakthrough about 8 hours into that session.

It originally included a way for users to select a unique color for each member of their four. I ended up dropping the color picker to stick with the album’s color choices, simplify the dev, and lower the barrier of creation. Also, my buddy Johannes said, “Users are bad at picking four colors that look nice together.” :-D

This project served as a proper renewal of my love and understanding for the model-view-collection goodness that is Backbone.JS. I was able to setup a a few models and collections for both the player and editor that effectively powered the entire user experience, client side, from a single page. And thanks to Backbone, all views associated with these models change automatically when they get created, updated, or destroyed.

Take a four Member model for example. Upon accepting the Facebook ID of a particular friend from the select box, the app creates a new Member model using the given user data:

Member.create({uid: 124, name: "Kele Okereke", position: 2});

This single line of code transparently posts to a member creation action on my server that responds with a success or failure. Upon success, Backbone initializes the newly created member and creates the appropriate view for it. It also checks to see if you’ve created four total members and if so, flips the view from editing to publish mode. Abracadabra!

Another big component of the client was Facebook. And while I’ve tried to keep up with the numerous changes to their developer platform over the years, I still went into this idea basically knowing zero. But alas, the days of server-side only authentication are over, and the developer docs have a nice overview of of the JavaScript SDK in action.

Authenticating a user and pulling a friends list is pretty straight forward, but what about posting a dynamically generated photo story with four tagged friends? Challenge accepted:

FB.api('/me/photos', 'post', { message: "Here's my FOUR. Who's in yours? http://four.blocparty.com", url: PHOTO_URL, tags: [ { tag_uid: Members[0].get('uid'), x: 25, y: 25 }, { tag_uid: Members[1].get('uid'), x: 75, y: 25 }, { tag_uid: Members[2].get('uid'), x: 25, y: 75 }, { tag_uid: Members[3].get('uid'), x: 75, y: 75 } ] }, function(response) { // posted! });

So, apart from a few cross-domain issues, developing with Facebook’s JavaScript SDK was actually quite fun. 7/10 would dev again.

I set my hipster stack aside for a second in exchange for a rack based Sinatra application, because I had a few Ruby gems in mind when conceptualizing this and I needed a quick and easy database infrastructure for storing users and members. I chose the well documented ORM, DataMapper, to create a User model and a many-to-many model called Memberships. Every user had X amount of member users through this group membership model. Or in code speak:

class User has n, :memberships, :child_key => [ :source_id ], :order => [ :position.asc ] has n, :members, self, :through => :memberships, :via => :target, :order => [ :id.asc ] end class Membership belongs_to :source, 'User', :key => true belongs_to :target, 'User', :key => true end

I then wrote a light-weight API to handle the creation, deletion, and updating of members when communicated with the client. In other words, CRUD! Each of these actions returned a JSON representation of the model in question.

As for those dynamically generated images… :-)

I’ve been wanting to use this trick for some time now as I have an unhealthy obsession [2] with the idea of using a server to process things like video, audio, and yes, images. This was actually a pretty basic example of this technique, and all it took was the Ruby gem MiniMagick to make it happen. Let’s look at an example of coloring a friends photo once they’re selected:

def colorize manipulate! do |img| img.combine_options do |c| c.colorspace 'Gray' c.fill '#C32025' c.tint '100' end img = yield(img) if block_given? img end end

Magick? You fucking bet. This was translated into a CarrierWave post processor that was called simply by supplying the remote URL to a friend’s Facebook profile photo. You know what else rules about CarrierWave? S3 support. So, once configured, all I needed to do was this:

member.remote_photo_url = "http://graph.facebook.com/#{ UID }/picture"

And this happened:

The photo was grabbed from the remote Facebook URL and cached locally. It was then resized, cropped, grayscaled, and tinted according to a dynamically supplied color. Finally, the photo was saved to my S3 bucket and stored as a CarrierWave file representation in my local database.

Seriously. Now if that doesn’t give you a nerd boner, I honestly don’t know what would. You have one? Good. You’re welcome.

I hope this gives you a nice overview of what goes into an intense two week project from concept to reality. But you don’t have to take my word for it… go experience the site and listen to the new record. It’s damn good. “Kettling” is my jam!

As always, thanks for listening. If you have any questions or comments, feel free to email or tweet me. And if you can’t get enough of this sort of stuff, subscribe to my email list. I promise not to spam you.

[1] The band was on hiatus from 2009 to 2011.

[2] Johannes and I wrote a service called Waveform.js to convert SoundCloud waveform images in an array of floating points.

101 Kudos