node package manager
Loosely couple your services. Use Orgs to version and reuse your code. Create a free org »



A tool for building static sites with gulp. Inspired by wintersmith.

This module's API is stabilizing but may change.


  • Parse files with or without YAML headers
  • Apply template using engine(s) of your choice
  • Supports generators (for things like pagination and A/B testing)
  • Supports parsing Polymer/htmling templates


Here's an example gulp task.

gulp.task('build-html', function () {
  // Create a "wagon" to hold these statics.  You can create multiple "wagons" 
  // to use different pipelines for different static file definitions. 
  var wagon = wainwright();
  // Apply templates to static file definitions.  By default, `templateDirectory` 
  // is set to `./templates`, but can be overridden when creating a wagon. 
  var templated = gulp.src('./content/**/*').pipe(wagon);
  // Write the processed pages to the build directory. 
  // Generate the blog list pages.  The `metadata` method returns a stream of 
  // internal wainwright contexts.  The processed contexts built from the file, 
  // its template, and its metadata can be filtered by path using the same 
  // syntax as `gulp.src`. 


An example of a paginator i.e. for a list of articles generated from static blog entry files.

var wainwright = require('wainwright');
var util = require('util');
var path = require('path');
var deco = require('deco');
var es = require('event-stream');
var paginator = module.exports = function (options) {
  var n = 0;
  var metadata = { articles: [] };
  var defaults = {
    template: 'blog/archive.hogan',
    first: 'blog/index.html',
    tail: 'blog/page/%d/index.html',
    templateDirectory: './templates',
    perPage: 3
  options = deco.merge(defaults, options);
  var stream = es.pipeline(
      function (article) {
        n += 1; = Math.ceil(/ options.perPage);
        metadata.cwd = article.cwd;
        metadata.base = article.base;
        metadata.template = options.template;
        metadata.templateDirectory = options.templateDirectory;
        // Build metadata for paginator page. 
        // The first archive page gets a special path.  The rest 
        // use a path based on their page number. 
        if ( === 1) metadata.path = options.first;
        else metadata.path = util.format(options.tail,;
        // Set path to absolute path. 
        metadata.path = path.resolve(article.cwd, article.base, metadata.path);
        // If not at per-page limit, wait until then. 
        if (% options.perPage !== 0) return;
        // The archive page has been fully built. 
        this.emit('data', metadata);
      function () {
        // Emit the last page if necessary and end the stream. 
        if (% options.perPage !== 0) this.emit('data', metadata);
    // Apply any templates specified by the metadata. 
    // Convert the metadata into an output file. 
  return stream;

©2014 William Riley-Land