Skip to content


Subversion checkout URL

You can clone with
Download ZIP
My fork including new commits of CoffeeKup, html markup as CoffeeScript.
CoffeeScript JavaScript
Branch: master
Pull request Compare This branch is 8 commits ahead, 83 commits behind mauricemach:master.

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.


This is an interim fork as @mauricemach looks very busy.


Markup as CoffeeScript

In celebration of whyday, here's a revisiting of Markaby's concept, this time with the fine flavour of fresh CoffeeScript:

doctype 5
html ->
  head ->
    meta charset: 'utf-8'
    title "#{@title or 'Untitled'} | My awesome website"
    meta(name: 'description', content: @description) if @description?
    link rel: 'stylesheet', href: '/stylesheets/app.css'
    style '''
      body {font-family: sans-serif}
      header, nav, section, footer {display: block}
    script src: '/javascripts/jquery.js'
    coffeescript ->
      $().ready ->
        alert 'Alerts are so annoying...'
  body ->
    header ->
      h1 @title or 'Untitled'
      nav ->
        ul ->
          (li -> a href: '/', -> 'Home') unless @path is '/'
          li -> a href: '/chunky', -> 'Bacon!'
          switch @user.role
            when 'owner', 'admin'
              li -> a href: '/admin', -> 'Secret Stuff'
            when 'vip'
              li -> a href: '/vip', -> 'Exclusive Stuff'
              li -> a href: '/commoners', -> 'Just Stuff'
    section ->
      h2 "Let's count to 10:"
      p i for i in [1..10]
    footer ->
      p 'Bye!'

Live demo at


  • Your rendering logic in a hell of a clean, expressive and flexible language.

  • Embedded templates (one-file apps FTW!) that you can still recognize.

  • The same template language and implementation in node.js or the browser.

  • The most efficient CoffeeScript "filter" possible in a template engine (based on cutting edge ".toString()" technology).

  • Easily extend it into your own higher-level "dsl" by defining helpers as locals (see below).

  • Great performance (see cake benchmark).

  • Precompile your templates to standalone functions.

  • Works with both coffeescript and javascript apps.

  • HTML 5 ready! Boring legacy doctypes and elements also available.

  • Optional HTML auto-escaping (or you can use the h helper).

  • Optional output formatting with indentation.

  • It's just coffeescript! Syntax checking, highlighting and other goodies are already available.


Just grab node.js and npm and you're set:

npm install coffeekup


coffeekup = require 'coffeekup'

console.log coffeekup.render -> h1 "You can feed me templates as functions."
console.log coffeekup.render "h1 'Or strings. I am not too picky.'"

Defining locals and context variables:

template = ->
  h1 @title
  form method: 'post', action: 'login', ->
    textbox id: 'username'
    textbox id: 'password'
    button @title

helpers =
  textbox: (attrs) ->
    attrs.type = 'text' =
    @input attrs

console.log coffeekup.render template, context: {title: 'Log In'}, locals: helpers

Precompiling to functions:

standalone_template = coffeekup.compile template
console.log standalone_template(context: {foo: 'bar'}, locals: {ping: 'pong'})

With zappa:

get '/': ->
  @users = ['bob', 'alice', 'sinatra', 'zappa']
  render 'default'

view ->
  for u in @users
    a href: "mailto:#{u}", -> u

With express:

app.register '.coffee', require('coffeekup')
app.set 'view engine', 'coffee'

app.get '/', (req, res) ->
  # Will render views/
  res.render 'index', context: {foo: 'bar'}

With meryl (see also their own take):

meryl.h 'GET /', (req, resp) ->
  people = ['bob', 'alice', 'meryl']
  resp.render 'layout', content: 'index', context: {people: people}
  templateDir: 'templates'
  templateExt: '.coffee'
  templateFunc: coffeekup.adapters.meryl

On the browser:

<script src="template.js"></script>
  $('body').append(template(context: {foo: 'bar'}));

This is one of many browser deployment possibilities, pre-compiling your template on the server to a standalone function. To see all serving suggestions, check out regular, decaf and crème.


$ coffeekup -h

  coffeekup [options] path/to/

  -w, --watch        watch templates for changes, and recompile
  -o, --output       set the directory for compiled html
  -p, --print        print the compiled html to stdout
  -f, --format       apply line breaks and indentation to html output
  -u, --utils        add helper locals (currently only "render")
  -v, --version      display CoffeeKup version
  -h, --help         display this help message

See /examples for complete versions. Please note that even though all examples are given in coffeescript, you can also use their plain javascript counterparts just fine.

Change Log:

v0.2.3 (2011-05-06):

  • Compatible with npm 1.x.
  • Converting any ampersands (instead of /&(?!\w+;/) to & when escaping html.
  • New CLI option -o / --output DIR.
  • Self-closing tags are now: 'area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'link', 'meta' and 'param'.

v0.2.2 (2011-01-05):

  • Updated to CoffeeScript 1.0.0 and node 0.2.6/0.3.3.

v0.2.1 (2010-11-09):

  • Updated to CoffeeScript 0.9.5 and node 0.2.5/0.3.1.
  • Fixed string templates compilation in opera.

v0.2.0 (2010-11-09):

  • Huge performance gains, now among the fastest. See cake benchmark.
  • Compile templates into standalone functions with coffeekup.compile.
  • Option format to add line breaks and indentation to output.
  • Escape HTML automatically with the autoescape option, or manually with the h local.
  • CLI behaviour closer to CoffeeScript's: compiles to filename.html by default, can watch and recompile with -w.
  • CLI -u/--utils option to make build-time utility locals available to templates (currently only render).


Latest version tested with node 0.4.7 and CoffeeScript 1.1.0.

Something went wrong with that request. Please try again.