A Grunt templating plugin to generate static HTML files from given pages, templates and partials written in either pure HTML, doT.js, or markdown.


Stencil is a Grunt plugin for templating that generates static HTML files from given components. Stencil provides the following:

  • A way to modularise your HTML source files: each file can include an arbitrary number of partial files, or be wrapped with a template file.
  • Built in support for the doT.js templating language, which allows passing of arbitrary variables to your HTML files.
  • Built in support for markdown
  • Meta data headers in the beginning of each file to specify variables that should be used in the file (that are accessible from partials included in the file, and templates the file is injected into).

See the Wiki pages for full documentation.

This plugin requires Grunt ~0.4.1

If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a Gruntfile as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:

npm install grunt-stencil --save-dev

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:


A more detailed explanation of all options can be found in the Wiki.

Each of the following is optional.

Type: Object Default value: {}

An object that specifies the template settings that are passed to the doT compiler (see doT.js).

Type: Object Default value: {}

Initial environment seen by all compiler, doT.js sees it as it. This environment is for each file with their header fields.

Type: String Default value: "."

A String value specifying the location of all templates. When specified, this will allow to call templates in pages' meta data without the full path to it (the specified templates will be prepended).

Type: String Default value: "."

A String value specifying the location of all partials. When specified, this will allow to call partial include functions without the full path (the specified partials will be prepended).

Type: String | RexExp Default value: /\r?\n\r?\n/

A String value specifying the characters to search for when separating meta data from the content of a file. By default, the JSON header of a file is considered to end after the first blank line in the file.

An elaborate list of examples can be found in the Wiki.

In your project's Gruntfile, add a section named stencil to the data object passed into grunt.initConfig().

  stencil: {
    options: {
      // Task-specific options go here. 
    your_target: {
      // Target-specific file lists and/or options go here. 

Grunt's rules for defining target and destination files apply, but care needs to be taken to make sure each input page maps to a single output file.

In this example, doT's it object is used to specify the location of script files and the main title of all pages; and the location of partials and templates is given. All pages in pages/ will be compiled to .html files in tmp.

  stencil: {
    main: {
      options: {
        env: {
          title: "Stencil",
        partials: "content",
        templates: "templates"
      files: [
          expand: true,
          cwd: "src/pages/",
          src: "**/*.dot.html",
          dest: "tmp",
          ext: ".html",
          flatten: true

In lieu of a formal styleguide, take care to maintain the existing coding style. Lint and test your code using Grunt. Please ignore W092 errors (wrapping regexps). The warning will show up until there's an option to disable it in jshint.

You can run the test suite with grunt test or grunt testv for more verbose output.

Each new feature ough to have full test coverage. We usually start by writing a fixture which is a pair of two file: the one to process (the fixture) and it's expected output. Fixture are html or md files in spec/fixtures. Any partials and templates required by this fixture should be stored in spec/partials and spec/templates, respectively. The expected output of a fixture should be put in spec/expected.

Once we run tests and the fixture is failing, we can implement any necessary feature by starting with writing specs (unit tests) in the spec directory, (like spec/my_new_feature_spec.js) and then implementing it in lib directory (lib/my_new_feature.js).

Once all the unit tests pass, we can integrate new code back to the task with making the fixture test pass in mind :) .

If you take a look at any file in lib/ you can notice that there's no dependencies between modules. All dependencies are injected in the task file tasks/stencil.js. That's the place where the integration happens.

  • version 1.1.0 (1st June, 2014) - apply doT to all HTML files
  • version 1.0.2 (10th December, 2013) - Windows compatibility
  • version 1.0.1 (24th November, 2013) - fix for new markdown version
  • version 1.0.0 (7th October, 2013) - first stable release
  • version 0.1.0 (4th October, 2013) - big refactor and change of specification
  • version 0.0.3 (19th September, 2013) - fix dependencies in package.json
  • version 0.0.2
  • version 0.0.1 (16th September, 2013)