Build a lightning fast Web app with Spine

The way we program is always evolving, and Web apps are no exception. The surge in mobile-app development (iOS and Android) has reminded programmers about the beauty of pretty, well-funded commercial APIs. Developing apps for the Web can be extra frustrating, comparatively, due to limited functionality and differences in Web browsers and slow-evolving “standards” that define functionality. Desktop apps tend to be much faster than Web apps because they operate “close to the user” — on his CPU. Web apps are different from Desktop apps because much of their processing happens at a remote location — the server. There is an exception — the front-end of a Web app (JavaScript) runs “close to the user” — on his CPU.

One of the really beautiful things about developing apps for the Desktop (or mobile) is the “MVC pattern”. Ruby on Rails and other Web app frameworks have popularized a type of MVC for the Web called “Model 2″, but it’s not good enough. With Model 2 Web apps, the user waits while the server combines templates with data and sends the output to the Web browser.

Web apps can be a lot better than that. If you haven’t built an app with Backbone.js or Spine.js yet — you’re in for a treat. Backbone and Spine are “client-side MVC” frameworks for the JavaScript portion of your Web apps. By putting a Model (description and storage of your app’s data) in the client, they make it possible to show the user his data immediately after he manipulates it. This makes a huge difference to the perceived speed of an app.

In the background, the Model syncs its data with server-side storage. Backbone and Spine make it easy to store your app’s data in HTML5 LocalStorage or using Ajax to sync with a HTTP API on the server.

Here’s an example client-side MVC app, written in Spine (and supported on the back-end by Structal, a server-side HTTP app I wrote).

The two main parts of your Spine app are its Model and Controller. The Model is a description of the classes of data in your app and the specific field names in your data storage. The Controller is a piece of code that hooks to and captures events from the user interface and Model.

Creating a Spine Model for the “posts” collection:

var Post = Spine.Model.sub();

Post.configure( 'Post', 'author', 'title' );

The Model describes a single Post, in the collection of posts in our new blogging app. The first line creates a Model in a variable called Post, which is a subclass of Spine.Model. The second line fires the Post Model’s configure method, and tells it that the Model is called “Post” and it has two fields in storage named “author” and “title”.

Spine and Backbone are different in little ways, they are both terrific. I picked Spine for this tutorial because it feels a little more fun to use. Backbone has a much larger community and a much more stable API.

Now that we have a Model, we need to tell it how to store its data. We’ll extend the Post Model with Ajax, which tells Spine to save all of that Model’s data to a remote server using GET, PUT, POST and DELETE. I’m tempted to say something about Restful URLs here (Spine and Backbone use the same URLs) but after following Roy Fielding’s blog I’ve learned that most of what we have all been thinking was Restful was really not at all.

Post.extend( Spine.Model.Ajax );

This line of code tells Spine to store the Post Model’s data on the server, not in HTML5 LocalStorage.

That’s all we have to do with the Model — not too bad, eh? The Controller is pretty approachable as well, here’s an example:

Let’s assume that you have some HTML with three elements: an unordered list of posts, an input field for typing the title of a new post, and a button to click to create the post.

<ul class="posts"></ul>

<input type="text" id="title" />

<button class="create">Create Post</button>

Next, you will need to configure your new Controller object and create a few methods on it. Configuration involves specifying the elements and events that the controller is interested in. The elements we want to tell the Controller about are the input field and the list:

var Posts = Spine.Controller.sub({

 elements: { // the elements array

  ".posts": "posts",

  "input[type=text]": "input"



Here, we’ve created a Spine Controller by subclassing Spine.Controller. On the Controller, we’ve added an elements array that links parts of our user interface to local references. By doing this, our Controller can refer to this.input instead of $(“input[type=text]) — much cleaner.

init: function() { // the init() method of the Controller

 Post.bind( 'refresh change', this.proxy( this.render )); // hook to the refresh and change events of the model

 Post.fetch(); // do a GET request to the server: /posts


The Controller’s init() method is important — this is where the Post model is connected to our Controller. The first line says that Post Model is told to notify the Controller (run its render() method) when data refresh and change events occur (this is where the real difference between Model 2 and MVC come into play — here we are using the “observer pattern” — an essential MVC ingredient mostly missing from Model 2 apps. On the second line, the Post model calls its fetch() method to do a GET to the /posts URL and get JSON back with a list of posts. Calling Post.fetch() will trip the Controller’s render() method, causing the posts to be displayed in the unordered list.

render: function() {// the render() method of the Controller

 posts = Post.all(); // fetch all of the posts from the Model

 for (p in posts) // loop over each post

  this.posts.prepend(Mustache.to_html(tpl,posts[p])); // tpl is some Mustache HTML template data, '<li>{{title}}</li>'


Here we have the render() method — which gets triggered by the refresh and change events on the Model. When render() is called, the browser fetches the list of posts from the server by calling the Post Model’s all() method. Then, for each post it uses this.posts (the shortcut to the unordered list, described in the elements array) and calls prepend() to pop a Mustache-rendered list item onto the unordered list.

Adding events to our controller is easy — the following code reads as follows: “connect the ‘click’ event of any elements of class ‘create’ (the button in our HTML) to this Controller’s ‘create’ method” — i.e. when the button is clicked, fire this Controller’s create method.

events: { // the events array

 'click .create': 'create', // hook the click event of the button


The create() method calls the Post Model’s create() method, passing it the data for a new post. You can see a reference to this.input — that is the shortcut to the form text input box — defined in the Controller’s elements array).

create: function() { // the create() method of the Controller

 p = Post.create({ author:'', title:this.input.val() }); // create a new post with an author and title

 this.input.val(''); // erase the title from the text box


The complete source code to this example can be found on Github.

Build a real-time microblog w/ajax data model sync

Structal is a new tool that mates the new client-side MVC frameworks (Spine and Backbone) with a back-end that provides automatic ajax data model Sync, and real-time JSON change feeds for each resource (SQL or NoSQL database table).

You can get the code at github, here’s a quick microblog Structal app:

class Posts extends Controller {
function init() {
// controller observes Post
// model's "create" event
Post::bind( 'create', 'addChange' );
function afterAction() {
// hook controller's "after"
// event to get/put/post/delete
trigger_after( strtolower($_SERVER['REQUEST_METHOD']) );

By extending Controller, we are enabling the back-end to provide automatic Model-sync via the built-in HTTP methods GET/PUT/POST/DELETE. The Spine.js or Backbone.js front-end Models will use Ajax to call the HTTP methods and pass data back and forth to sync the client Models with the server database.

Also, we need a server-side Model to go with the Controller, in index.php:

class Post extends Model {
static $id = array( 'type'=>'String', 'key'=>true );
static $author = array( 'type'=>'String' );
static $title = array( 'type'=>'String' );

And a client-side Model definition in app.js:

var Post = Spine.Model.sub();
Post.configure("Post", "author", "title");

Now that the server-side is configured, we can create a pair of client-side Controllers with Spine, in the app.js file:

  var Posts = Spine.Controller.sub({
    init: function() {
      this.posts = new PostList({ el:$("#content") });
        "/": function(params){
      this.navigate( '/' );
  var PostList = Spine.Controller.sub({
    events: {
      'click .create': 'create',
    elements: {
      ".items": "items",
      "input[type=text]": "input"
    init: function() {
      Post.bind( 'refresh change', this.proxy(this.render));
      //setInterval(this.poll, 5*1000);
      var el = this;
      $.get('tpl/posts/list.html', function(data) {
    render: function() {
      var el = this;
      $.get('tpl/posts/item.html', function(data) {
        posts = Post.all();
        for (p in posts)
    create: function() {
      item = Post.create({ author:'', title:this.input.val() });
  return new Posts({el:$("body")});

Here's the template code for tpl/posts/list.html
<ul class="items"></ul>
<input type="text" id="title" />
<button>Create Post</button>

#Swat0 and a Salmon-like flow for RSS

This summer I joined other federated social Web implementors at the Federated Social Web Summit, it was a great, collaborative atmosphere where everyone was given space to share their implementation details and ideas for the future.

As an early implementor of StatusNet’s original Open Microblogging federation protocol, I was really interested to catch up on OStatus and find out about Diaspora and how it would work. The event did not disappoint, I sat next to Raffi from Diaspora and had a chance to talk protocols with Rob Dolin, Joseph Smarr, Tantek Çelik, Brett Slatkin, Evan Prodromou, Zach Copley, David Recordon and many more.

When the summit wrapped up, Evan, Dave and Tantek introduced an “acid test” for social network interoperability, the acid test was dubbed “SWAT0″ (Social Web Acid Test Zero). To pass the test, two or more codebases would allow a user to tag another user in a photo, comment on the photo, and notify users of activity, all of this between two or more social networks using open standards.

Last summer I was briefly in the geek news when announced that they were closing their doors and FriendFeed was snapped up, I called in to the Bad Hair Day podcast and explained, my open source replacement. Before the rssCloud meetup, Michael Sullivan (@sull) wrote a post “Conversations in the Cloud” and came up with the idea to use my domain (sounds like “reply”) to create an RSS namespace:

As I thought about simple ways to achieve the acid test, I remembered Michael’s post. By late August I had a working version of the SWAT0 flow (before StatusNet’s Sept. 10 SWAT0 release) using StatusNet and OpenMicroBlogger. I’ve contributed to StatusNet before — I created the “Templonica” plugin. So I already had a place to publish my StatusNet/inReplyTo commits: Gitorious.

Joe Gregorio’s Comment API is closely related to TrackBack and PingBack, I combined that with the <channel> element’s <textInput> tag for the first version, then I talked to Michael and started working on a namespace (see below). The purpose of the inReplyTo namespace is to allow aggregators and readers to notify the feed origin about comments that are “in Reply To” the original.

Here’s an example: Bob wants to reply to Alice (she’s using a different blogging service than he is). When he publishes a reply to his own feed, his application reads her feed’s inReplyTo elements and uses the information to ping her channel-level form handler. The details of this interaction are described in a new namespace — inReplyTo (1).

Bob’s reply will have a <comments> item-level element in his feed, a link to Alice’s post that he replied to. When Alice’s application uses WebFinger to discover and read Bob’s feed, it can use the <comments> element to associate Bob’s reply with the appropriate thread, or her application could show all replies in a tab, even from people she’s not subscribed to.

If you are interested in participating in defining or implementing the inReplyTo protocol, contact @sull or @brianjesse.

####### inReplyTo #########

Extension: inReplyTo

Extension Name: inReplyTo

Purpose: Applications can automatically send comment notifications by pinging the channel’s inReplyTo form handler url.

Declaration: The name space for inReplyTo is defined at

<rss version=”2.0″ xmlns:inReplyTo=””>

Elements: All elements are sub-elements of the <channel> tag.

<inReplyTo:url> The url of the form handler

<inReplyTo:user> An identifier of the user being replied to

Applications append the inReplyTo url with the guid and other attributes to identify the item being commented on. It can then ping the combined url when a new comment is created.



When a comment is created, the application combines the channel’s inReplyTo url ( with the item guid and other inReplyTo elements, and POSTs a request to the combined url: (


Social Web Acid Test Zero from Brian Hendrickson on Vimeo.

we need to create the data web

Later today i’ll share my ideas about 2-way feeds, OpenMicroBlogger and StatusNet. In 2008 I implemented the Open Microblogging 0.1 specification, in 2009 I migrated the OpenMicroBlogger federation feature to rssCloud because there was good support in WordPress and as well. Now in 2010 i’ve added (partial) OStatus capability and helped with development of an upstream-commenting extension for RSS feeds that can use Webfinger for discovery.

a #wp plug-in for mashing up Buzz, Facebook, Twitter and RSS

(this is a post I wrote about a tool called rssLike – it was published on the Structal blog:

Hi, thanks for stopping by to learn more about @rssLike.

rssLike is a standards-based Like button that combines Facebook, Twitter and Google Buzz together into a single button. It also publishes Likes from your Web site as a real-time feed.

rssLike is now available as a safe, easy-to-install WordPress plug-in (latest version is 0.2.3) download it from Github.

To use rssLike, first set a password (SSL encrypted) at, then copy the settings into your WordPress admin dashboard.

When you post, include the following string: [ rssLike ] (no spaces) and that will make the three-network Like button appear alongside your article.

rssLike Screen Shots

Like this post? Use rssLike (below) to like it! Thanks