node package manager



metaserve makes web application prototyping quicker by compiling and serving assets built with meta-languages[1] such as CoffeeScript, Jade, and Styl (currently the full list).

Use as a command or as middleware to handle requests for e.g. js/myapp.js by run-time-compiling the js/ source file into Javascript. Similar to (but less contrived than) the Rails Asset Pipeline.

Metaserve is based on a collection of plugins, which by default support Jade (to HTML), CoffeeScript (to Javascript), and Sass (to CSS) to support the Prontotype stack. New languages are easily added with a simple plugin architecture.

As a command

Install with npm install -g metaserve

Use within a directory that has a bunch of .jade, .sass and .coffee. Run metaserve with optional arguments --host and --port. Defaults to

As middleware

Install with npm install metaserve

Use by supplying a base directory, then hooking it in as Express/Connect middleware...

var express = require('express');
var metaserve = require('metaserve');
app = express();

... or as a fallback method in a standard http server:

var http = require('http');
var metaserve = require('metaserve')('./app');
var server = http.createServer(function(req, res) {
    if (req.url === '/dogs') {
        return res.end('woof');
    } else {
        return metaserve(req, res);

Writing Plugins

A plugin is simply a Javascript module with a few fields:

  • ext
    • The extension that this plugin will match, e.g. "coffee"
  • default_config (optional)
    • Default config which will be extended and passed in as the config argument to the compiler function
  • compiler(filename, config, context, cb)
    • A function that should transform some source file and call back with an object {content_type, compiled}

Here's a simple plugin that reads and reverses a text file:

var fs = require('fs');
module.exports = {
    ext: 'txt',
    compile: function(filename, config, context, cb) {
        fs.readFile(filename, function(err, source) {
            if (err)
                return cb(err);
            else {
                source = source.toString();
                reversed = source.split('').reverse().join('')
                cb(null, {
                    content_type: 'text/plain',
                    compiled: reversed

By passing an object of compilers to the metaserve middleware, paths that match the extension key (here "txt") will be run through this plugin:

app.use(metaserve('./app', {
    txt: require('./reverse-plugin')

Default Plugins


  1. Not to be confused with the real definition of a Metalanguage.