Brunch / Marionette sample application

The other day I ran into Brunch. You can visit the site to get more information, but in a nutshell it’s a build tool. I decided to play with it a bit.


Installation is simple:

$ npm install -g brunch

Creating a sample project

In order to create a new project, a skeleton is used. At the moment, there are a few dozen skeletons listed here. I am going to use this, which is “Brunch with Coffee Script, Stylus, Backbone, Marrionette, and jQuery.”.

To create the project, this needs to be done:

$ brunch new

After the skeleton is cloned and the libraries downloaded, you will have something like this:



  • is a brunch configuration
  • bower.json is bower configuration
  • vendor is where brunch will put the bower-fetched dependencies (which are managed by bower under bower_components)
  • app is where files related to our application should go

In order to build it for the first time, do this:

$ npm install
$ brunch build

After this, another folder appears – public. This one contains compiled files:



When developing, all the compilation that needs to be done can be done automatically. This is the watching functionality of brunch. Just invoke this:

$ brunch watch --server

The --server parameter will start a development Web server (defaults to localhost:3333).


The above skeleton already contains file. This one initializes Backbone.Marionette.Application and does nothing else. In order to display something, Marionette has a few concepts. This is I think best explained on the main page here, but briefly:

  • Template translates into a HTML that will be shown
  • View renders a template and handles events
  • Region defines a jQuery selector that will hold a View instance

View also depends on Backbone.Model or Backbone.Collection to hold the data that is used by a Template instance when rendering.

Basic app

Let’s do a small app – a bounded (to [-5, 5] integer range) counter. In brief:

  • Our model is a number
  • Our view is a text box and a button
  • Button click will make the model’s number to be increased by one

I’m also going to use Handlebars templates, so will first add this:

    "handlebars-brunch": ">= 1.0 < 1.8"

to the dependencies secdion of package.json, followed by:

$ npm install

Let's do this step by step.


I'm going to use the regular CommonJS modules here. Thus, when I say "this goes to file abc", it needs to be put in that file for the require logic to work. If you change the file names or the folders where they belong, please update the require lines appropriately. Just to make it simple, all files here will go to the root of app folder.


The main HTML in the skeleton is not surprisingly index.html. We just need to add one line in the body:

    <div id="main"></div>

As to why, it will be clear when we discuss the controller a bit later. This edit goes to assets/index.html.


Our model is simple:

module.exports = class Number extends Backbone.Model
    number: 1

  inc: ->
    @set 'number', @get('number') + 1

This goes to So we have:

  • Number class that extends Backbone.Model class
  • Default number is 1
  • Inc method that increases the number property
  • Emphasis on property here - calling set on number will send a change:number event, which we will use later


Template is simple as well:

<input id="number" type="text" value="{{number}}" readonly="false" />
<button id="inc">Inc</button>

This goes to number-template.hbs. We have this:

  • This is a Handlebars template
  • It contains two HTML elements - an input box to display our number
  • Both have the IDs that we'll reference later (#number and #inc)
  • Input has it's value set to {{number}} which Handlebars will render appropriately
  • It also has readonly set to false, just so user cannot change the value, as we don't have the binding for this update


View is simple, though a bit more complex than model:

module.exports = class NumberView extends Backbone.Marionette.ItemView
  template: require('number-template')
    'click #inc': 'inc'
    incInp: '#number'

  initialize: ->
    @listenTo @model, "change:number", @numberChanged

  numberChanged: ->
    @ui.incInp.attr 'value', @model.get 'number'

  inc: (evt) ->
    @trigger 'number:inc'

This goes to Here we have:

  • NumberView extends Backbone.Marionette.ItemView. This class is responsible for showing a single item, hence the name
  • We specify the template as number-template
  • The events says that when our button (HTML ID is #inc, our Inc button) is clicked, we invoke inc method on the view
  • ui property is just an alias map. It allows us to say @ui.incInp and reference the HTML element specified, in this case #number, which is our input element
  • initialize method binds a listener to our model. It says: whenever the model triggers change:number event, call our numberChanged function on this view
  • numberChanged is just updating the input with the number whenever it changes
  • inc method is the event listener for button click - it triggers number:inc event, which our controller is going to catch and then act appropriately


The controller looks like this:

module.exports = class NumberController extends Marionette.Controller
  initialize: (options) ->
    @model = options.model
    @view = options.view
    @listenTo @view, 'number:inc', @numberInc

  numberInc: ->
    newNumber = @model.get 'number'
    newNumber = -5 if newNumber > 5
    @model.set 'number', newNumber

Note that this (as per this doc paragraph) is not equivalent to the C in MVC. I'm however using it for this purpose only.

This goes to It has two things:

  • initialize method remembers the provided model and view instances and subscribes to number:inc event. This event is triggered from view when button is clicked, see above
  • numberInc is the method that encapsulates the business logic of our bounded counter. It will increase the number and make sure it stays in [-5, 5] range
  • Just a reminder here: doing @model.set will trigger a change:number event, which will complete the cycle by going to our view and rendering it via numberChanged method, see above

Application initialization - wiring all this together

We need to update to wire this together. We can also do this in, depending on how we want to do the separation of concerns. Here's how it looks:

NumberModel = require('number-model')
NumberView = require('number-view')
NumberController = require('number-controller')

class Application extends Backbone.Marionette.Application
  initialize: =>
    @on 'initialize:after', @startHistory

    model = new NumberModel
    view = new NumberView model: model
    new NumberController model: model, view: view

    @addRegions mainRegion: '#main' view


  startHistory: (options) => Backbone.history.start()

module.exports = Application

Here we do the following:

  • Import the necessary classes, NumberModel, NumberView and NumberController
  • In initialize, instantiate the model, view and controller and wire them up as needed
  • Add a region - this references the #main div that we added to index.html
  • Finally, show the view into this region and start the app


I can say this about the simple app:

  • Brunch makes it very easy to start the project - installation and getting up and running from the appropriate skeleton is just a few commands away
  • It's watch command is a one-step way to a very good development experience - it compiles templates, CoffeeScript files, bundles everything and a refresh of the dev Web server just brings the latest - like it a lot
  • Bower allows for a very nice dependency management
  • Marionette provides a very good and simple framework for decoupling things into sensible, well-contained units (models, templates, views, controllers, application - and there are also layouts and under-the-cover event aggregator that we actually used above)

All in all, I think this is a very good model - I hope to use it going forward.