Batman.js is no longer in production at Shopify and is not actively maintained.

This website is left for reference (and for old times' sake).



Your app is the namespace for all your other components. It extends Batman.App and defines routes.

You can define global accessors and functions on the app, too.

    class Gotham extends Batman.App
      @root 'superheros#index'
      @resources 'superheros', 'villains'
      @route '/404', -> alert("Page not found!")

      @classAccessor 'cityIsSafe', ->
        heroCount = Gotham.Superhero.get('all.length')
        villainCount = Gotham.Villain.get('all.length')
        heroCount > villainCount
# models/
    class Gotham.Superhero extends Batman.Model
      @resourceName: 'superhero'
      @persist Batman.RestStorage
      @encode 'name', 'wears_cape'

      @validate 'name', presence: true

      @belongsTo 'hero_group'
      @hasMany 'superpowers', saveInline: true

      @accessor 'canSaveGotham', ->
        @get('superpowers.length') > 3


Models represent the "business objects" in your app and connect those objects to a backend, like a JSON API. Models usually include:


Controller actions are executed by routes in your app. They load data and render views.

# controllers/
    class Gotham.SuperherosController extends Gotham.ApplicationController
      routingKey: 'superheros'

      index: (params) ->
        @set 'superheros', Gotham.Superhero.get('all')

      show: (params) ->
        Gotham.Superhero.find, (err, record) =>
          @set 'superhero', record

      edit: (params) ->
        Gotham.Superhero.find, (err, record) =>
          @set 'superhero', record.transaction()
<!-- html/superheros/index.html -->
    <h1 data-bind='"Superhero" | pluralize heroCount'></h1>

    <div data-foreach-superhero='superheros'>
      <h2 data-bind=''></h2>
      <span data-showif='superhero.wears_cape'>
        (Wears a Cape)
      <a data-event-click='removeHero | withArguments superhero'>
        Remove this superhero

    <a data-route=''>Add a Superhero</a>
# views/superheros/
    class Gotham.SuperherosIndexView extends Batman.View
      @accessor 'heroCount', ->

      removeHero: (superhero) ->


The view layer includes two parts: HTML templates and views.

HTML Templates

Templates connect your app the DOM with data bindings. Batman.js maintains bindings, so the DOM and your app are always in sync.


Views provide context to HTML templates by defining:

You can also hook into the view lifecycle to setup, teardown and transition your views.

Batman Rdio

The demo app from the live tutorial on this site. Live example and source code.


A great place to get started with batman.js. Live example and source code.

Batman.js MVC Cookbook

Quick how-tos for common patterns in a batman.js app. Read Online.

Additional resources:

Mailing List

For the sake of asynchronous communication, most discussion and announcements about batman.js will take place via the mailing list, hosted on Google Groups.


batman.js is released as open source software under the MIT license. We invite you to download, modify, and use the code. If you do anything you think other people would find useful, we love pull requests!


Found a bug or other nasty in batman.js? It's still new, so it's bound to happen! We use GitHub's issue tracker to manage our issues.