docs: function getStatic(id, basedir, config, name, lesspaths, done) {
    if (arguments.length === 5) {
      done = lesspaths;
      lesspaths = name;
      name = 'config';
    }
    async.parallel({
      html: function (next) {
        var failhard = !!config.template;
        if (config.template && !config.template.match(/\.html$/)) return next(null, config.template);
        fs.readFile(path.join(basedir, config.template || 'config/' + name + '.html'), 'utf8', function (err, data) {
          next(failhard && err, data);
        });
      },
      js: function (next) {
        var failhard = !!config.script;
        fs.readFile(path.join(basedir, config.script || 'config/' + name + '.js'), 'utf8', function (err, text) {
          if (!failhard && err) return next(null, '');
          next(err, text + '\n//# sourceUrl=' + id + '/' + path.join(basedir, config.script || 'config/' + name + '.js') + '\n');
        });
      },
      css: function (next) {
        var failhard = !!config.style;
        fs.readFile(path.join(basedir, config.style || 'config/' + name + '.less'), 'utf8', function (err, text) {
          if (!failhard && err) return next(null, '');
          var source = '\n/** source: ' + id + '/' + (config.style || 'config/' + name + '.less') + ' **/\n';
          if (err) return next(err);
          if (config.style && config.style.slice(-5) !== '.less') {
            return next(null, text + source);
          }
          var fpath = path.join(basedir, config.style || name + '.less');
          
          less.render(text, {
            paths: [path.dirname(fpath)].concat(lesspaths || []),
            filename: fpath
          }).then(function(output) {
            next(null, output.css + source);
          }, function(error) {
            next(error);
          });
        });
      }
    }, function (err, data) {
      return done(err, data.html, data.css, data.js);
    });
  }