Having just rolled off a very long contract, I’ve finally found a little time to play around with new and interesting tech. To that end, I wrote up a small (but sweet, IMHO) realtime list web application using the Meteor framework.
What it looks like:
What it does: It’s a simple, mobile first, realtime sharing list application. I wrote it so my wife and I could have a shared list space for groceries, hardware store runs, etc. No need to text last minute additions. No apps to install. Just add items to the list. Everyone who’s on your unique list url sees the new thing immediately. Swipe left to delete. Swipe right to strike out. Touch to edit. That’s it. We’ve been using it heavily and it’s really handy. In reality, the app is little more than a conglomeration of the features offered by their nice little suite of demos (with some special sauce thrown in). So nothing ground breaking.
Background: If you haven’t heard of it, Meteor is a frighteningly ambitious full stack web application development framework. Take a gander at their Seven Principles to get an idea of the force and magnitude of their vision. It’s essentially beta software (at version 0.5.9 at the time of this writing). But, they’ve got funding and at least some semblance of a plan to produce revenue. Also, the offering currently has a polish beyond what you might normally expect from beta.
Preview Conclusion: Meteor is a fantastic early stage framework that shows great promise and will soon be a great platform candidate for certain types of realtime web apps. It’s probably going to have to throw in some more mobile-centric features (RESTful endpoints on the server, support or plugins for every manner of reactive, touch centric UIs, etc.) soon. But I have little doubt they will.
Reactivity is really a killer feature. Whether or not Meteor eventually gains traction, I suspect this pattern will be adopted widely by other frameworks. After developing a couple small applications in Meteor, I consider reactivity a sine qua non feature of web application development. With Meteor, you’ve got reactive datasources backing reactive computations backing live html template. This is a very slick way to deliver content realtime to the browser, as you’ll see.
Yada, yada. Time to show code. Here’s the server side publication of the two collections (lists & things) that the app uses:
Straightforward. Note that this code resides in a directory called server, so Meteor will not ship this code to the client. The client and the server do share collection notions, so those are declared in a file called model.js and shipped down to the client:
And, here’s the client code that subscribes to the collections published by the server above:
A couple of things to note about the things and lists subscriptions. The things subscription is tied to the current list identifier, so you only see relevant things. The list subscription handle (listsHandle) is tied to an empty loading div in the DOM. This ensures that the list has been loaded into the local collection from the server before it is accessed. I picked this handy little trick up from one of the official examples. It prevents you from getting empty collections when accessing them at startup (a source of frustration).
You’ll see the list handler detects if there is no list. In this case (e.g. you land on the naked domain for the first time), it creates one and reroutes the request to a unique url that corresponds to the list id. Share the url, share the list. The app uses backbone strictly for routing. The router implementation is straight from the Meteor examples.
The template.list.loading declaration is Meteor’s way of supplying data to the live html loading div in the list template (handlebars style).
Speaking of the view. Here is is in it’s entirety:
Not much to it. Some css ensures that the desktop version gets delete/strike out links instead of just touch gestures. BTW, I added touch/gesture support using the nice, lightweight hammer.js library. Hammer has been wired up to the list item html element via Meteor’s rendered event so that we can guarantee the element is already in the DOM:
Also note that we delete the items via Meteor.call(‘removeListItem’, id). This demonstrates how to invoke a method on the server rather than just deleting the record from the local collection and allowing meteor to automagically propagate that change to the server collection (an operation which we have expressly forbidden via the model allow declaration above).