node package manager


layouts NPM version NPM monthly downloads NPM total downloads Linux Build Status

Wraps templates with layouts. Layouts can use other layouts and be nested to any depth. This can be used 100% standalone to wrap any kind of file with banners, headers or footer content. Use for markdown, HTML, handlebars views, lo-dash templates, etc. Layouts can also be vinyl files.

(TOC generated by verb using markdown-toc)


Install with npm:

$ npm install --save layouts


var renderLayouts = require('layouts');


Basic example

In this example, two layouts are used:

  • the first layout, one, will wrap the string
  • the second layout, two, will wrap the first layout
var layouts = {
  one: {content: 'one before\n{% body %}\none after', layout: 'two'},
  two: {content: 'two before\n{% body %}\ntwo after'},
// `one` is the name of the first layout to use on the provided string 
renderLayouts('<div>Wrap me with a layout!!!</div>', 'one', layouts);

Results in:

two before
one before
<div>Wrap me with a layout!!!</div>
one after
two after


This example shows how to use nested HTML layouts to wrap content:

var layouts = {};
layouts.base = {
  path: 'base.tmpl',
  content: [
    '<!DOCTYPE html>',
    '<html lang="en">',
    '  <head>',
    '    <meta charset="UTF-8">',
    '    <title>Home</title>',
    '  </head>',
    '  <body>',
    '    {% body %}',
    '  </body>',
// this `nav` layout will be wrapped with the `base` layout 
layouts.nav = {
  path: 'nav.tmpl',
  layout: 'base',
  content: '<nav>\n{% body %}\n</nav>'
// this string will be wrapped with the `nav` layout 
var str = [
  '<ul class="categories">',
  '  <li class="active"> <a href="#"> Development </a> </li>',
  '  <li> <a href="#"> Design </a> </li>',
  '  <li> <a href="#"> Node.js </a> </li>',
// `nav` is the name of the layout to use 
renderLayouts(str, nav, layouts);

Results in something like:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
      <ul class="categories">
        <li class="active"> <a href="#"> Development </a> </li>
        <li> <a href="#"> Design </a> </li>
        <li> <a href="#"> Node.js </a> </li>


By default, {% body %} is used as the placeholder (insertion point) for content, but this can easily be customized with the following options:

  • layoutDelims: the delimiters to use. This can be a regex, like /\{{([^}]+)\}}/, or an array of delimiter strings, like ['\{{', '}}']
  • contentTag: the name of the content placeholder tag (defaults to body).



Apply a layout from the layouts object to file.contents. Layouts will be recursively applied until a layout is not defined by the returned file.


  • file {Object}: File object. This can be a plain object or vinyl file.
  • layouts {Object}: Object of file objects to use as "layouts".
  • options {Object}
  • returns {Object}: Returns the original file object with layout(s) applied.


var applyLayouts = require('layouts');
var layouts = {};
layouts.default = new File({path: 'default', contents: new Buffer('foo\n{% body %}\nbar')}),
layouts.other = new File({path: 'other', contents: new Buffer('baz\n{% body %}\nqux')});
layouts.other.layout = 'default';
var file = new File({path: 'whatever', contents: new Buffer('inner')});
file.layout = 'other';
applyLayouts(file, layouts);
// foo 
// bar 
// inner 
// baz 
// qux 



Breaking changes

  • renames layoutHistory to layoutStack
  • layouts in layoutStack are now the actual layout object, instead of the layout name


  • Adds support for a function as the last argument. If passed, the function is called on the file and each layout with this signature: fn(file, layout).


Breaking changes

  • The main layouts() function now expects a file object as the first argument. This can be an object with path, layout and contents properties, or a valid vinyl file. See the API docs for more details.


Breaking changes

  • change options.tag to options.contentTag


  • update tests to use assert instead of should


  • All view objects must now have a path property, following vinyl conventions.


Related projects

You might also be interested in these projects:

  • assemble: Get the rocks out of your socks! Assemble makes you fast at creating web projects… more | homepage
  • gulp: The streaming build system | homepage
  • handlebars-layouts: Handlebars helpers which implement layout blocks similar to Jade, Jinja, Nunjucks, Swig, and Twig. | homepage
  • inject-snippet: Inject a snippet of code or content into a string. | homepage
  • templates: System for creating and managing template collections, and rendering templates with any node.js template engine… more | homepage
  • verb: Documentation generator for GitHub projects. Verb is extremely powerful, easy to use, and is used… more | homepage
  • vinyl: Virtual file format. | homepage


Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.


Commits Contributor
131 jonschlinkert
26 doowb

Building docs

(This project's is generated by verb, please don't edit the readme directly. Any changes to the readme must be made in the readme template.)

To generate the readme, run the following command:

$ npm install -g verbose/verb#dev verb-generate-readme && verb

Running tests

Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:

$ npm install && npm test


Brian Woodward


Copyright © 2017, Brian Woodward. Released under the MIT License.

This file was generated by verb-generate-readme, v0.6.0, on August 07, 2017.