We gave a nod to CoffeeKup, Maurice Machado’s CoffeeScript ode to Markaby last month. Maurice is back with a new CoffeeScript ditty.

Zappa is a highly opinionated DSL for writing Node.js apps on top of Express – using CoffeeScript. Be sure and check out Episode 0.2.9 on CoffeeScript and Episode 0.3.1 on Websockets and Socket.IO for a little background if you missed them.

To get started, assuming you’ve got Node and Express installed, install Zappa via npm:

npm install zappa

You then can fire up your Zappa app from the command line:

$ zappa cuppa.coffee
=> App "default" listening on port 5678...

So what does a Zappa application look like?

Just like Sinatra, routes are mapped to handlers using the four HTTP verbs:

get '/:foo': ->
  @foo += '!'
  render 'index'

You can declare that index view in the same file with the view function:

view index: ->
  h1 'You said:'
  p @foo

Layouts? You bet:

layout ->
  html ->
    head -> title "You said: #{@foo}"
    body -> @content

Currently views and layouts support Coffeekup only, but that might change.

Async and Websockets

You can’t really talk about Node without discussing its inherent asynchronous nature. Zappa makes async style programming straightforward as well:

def sleep: (secs, cb) ->
  setTimeout cb, secs * 1000

get
  '/': -> redirect '/bar'

  '/:foo': ->
    @foo += '?'
    sleep 5, =>
      @foo += '!'

      @title = 'Async'
      render 'default'

view ->
  h1 @title
  p @foo

Zappa also has support for Socket.IO out of the box, so Websockets programming is a snap.

get '/': -> render 'default'

get '/counter': -> "# of messages so far: #{app.counter}"

at connection: ->
  app.counter ?= 0
  puts "Connected: #{id}"
  broadcast 'connected', id: id

at disconnection: ->
  puts "Disconnected: #{id}"

msg said: ->
  puts "#{id} said: #{@text}"
  app.counter++
  send 'said', id: id, text: @text
  broadcast 'said', id: id, text: @text

client ->
  $(document).ready ->
    socket = new io.Socket()

    socket.on 'connect', -> $('#log').append '<p>Connected</p>'
    socket.on 'disconnect', -> $('#log').append '<p>Disconnected</p>'
    socket.on 'message', (raw_msg) ->
      msg = JSON.parse raw_msg
      if msg.connected then $('#log').append "<p>#{msg.connected.id} Connected</p>"
      else if msg.said then $('#log').append "<p>#{msg.said.id}: #{msg.said.text}</p>"

    $('form').submit ->
      socket.send JSON.stringify said: {text: $('#box').val()}
      $('#box').val('').focus()
      false

    socket.connect()
    $('#box').focus()

view ->
  @title = 'Nano Chat'
  @scripts = ['http://code.jquery.com/jquery-1.4.3.min', '/socket.io/socket.io', '/default']

  h1 @title
  div id: 'log'
  form ->
    input id: 'box'
    button id: 'say', -> 'Say'

As a fan of CoffeeScript, I’ll be kicking the tires on this for my next Node app.

[Source on GitHub]


Have comments? Send a tweet to @TheChangelog on Twitter.

Subscribe to The Changelog Weekly – our weekly email covering everything that hits our open source radar.