Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Tree: a1cd027ae2
Fetching contributors…
Cannot retrieve contributors at this time
679 lines (437 sloc) 25.7 KB


Generator templates allow you to scaffold out a project using a custom setup of boilerplates, frameworks and dependencies. The basic application generated when calling yeoman init actually uses a generator itself and they can be quite powerful.

Some of the generators Yeoman includes out of the box include implementations for Backbone.js, Ember.js and Angular.js. These allow you to not only use complete boilerplates for an application but also scaffold out smaller parts such as Models, Views, Controllers and so on.

Getting Started

yeoman init generator

The yeoman init command uses templates and prompts to create the files needed for a project.

Running yeoman init --help by itself gives a list of available generators:

$ yeoman init generator
Usage: yeoman init generator GENERATOR [args] [options]


Please choose a generator below.


Note: You can install more generators through npm package and you can even create your own. Yeoman's own generators are available in a dedicated repository.

Using generators will save you a large amount of time by writing boilerplate code, code that is necessary for the app to work.

Let's make our own controller with the controller generator. But what command should we use? Let's ask the generator:

Note: Generators available may have help text. You can try adding --help or -h to the end, for example yeoman generate controller --help

.. Invoke controller ..
  yeoman init generator controller NAME one two three [options]

  -h, --help          # Print generator's options and usage
      --js-framework  # Js framework to be invoked
                      # Default: ember

The controller generator is expecting parameters in the form of generate controller ControllerName action1 action2

Let's make a Greeting controller with an action of hello.

$ yeoman init generator controller Greeting hello

What did this generate? It made sure a bunch of directories where in our application, and created a controller file, a view file and / or template file and a test file.

Yeoman comes with a generator for data models too.

$ yeoman init generator model

Creating and Customizing Yeoman Generators & Templates

  1. First Contact
  2. Creating Your First Generator
  3. Creating Generators with Generators
  4. Generators Lookup
  5. Customizing Your Workflow
  6. Customizing Your Workflow by Changing Generators Templates
  7. Adding Generators Fallbacks
  8. Application Templates

First contact

When you create an application using the yeoman init command, you are in fact using a Yeoman generator. After that, you can get a list of all available generators by just invoking yeoman init --help:

$ yeoman init
$ cd app
$ yeoman init --help

You will get a list of all generators that come with yeoman. If you need a detailed description for a given generator, you can simply do:

$ yeoman init generator [generator] --help

Creating Your First Generator

Generators are built on top of Grunt. Grunt provides powerful options parsing and a great API for manipulating files. For instance, let’s build a generator that creates an initializer file named initializer.js inside app/js/

The first step is to create a file at `lib/generators/initializer/index.js with the following content:

var util = require('util'),
    yeoman = require('../../../');

module.exports = Generator;

function Generator() {
  yeoman.generators.Base.apply(this, arguments);

util.inherits(Generator, yeoman.generators.Base);

Generator.prototype.createInitializerFile = function() {
  this.write('app/js/initializer.js', "// Add initialization content here\n");

write is a method provided by yeoman.generators.Base, and is a basic facade to the grunt.file API. When we "write" things, this happen relative to the working directory (that is the Gruntfile location, the Gruntfile is resolved internally, walking up the FS until one is found. This is most likely the root of the yeoman application).

Our new generator is quite simple: it inherits from yeoman.generators.Base and has one method definition. Each "public" method in the generator is executed when a generator is invoked (first level method in the prototype chain, eg. Base class method are not called).

There are two exceptions, generators won't run:

  • any method beginning with the _ prefix.
  • a constructor method, specifically used with generators written in CoffeeScript

Finally, we invoke the write method that will create a file at the given destination with the given content.

Note: Generators should execute their tasks synchronously. We currently lack the API to be able to do things asynchronously (which we might need). A this.async() method should be implemented, which returns a new handler to call on completion.

Now, we can see that the initializer generator available to use if we output the list of available generators in this application:

$ yeoman init generator

Usage: yeoman generate GENERATOR [args] [options]

Please choose a generator below.



To invoke our new generator, we just need to do:

$ yeoman init initializer

Before we go on, let’s see our brand new generator description:

$ yeoman generate initializer --help
.. Invoke initializer ..
    Create files for initializer generator.

Yeoman is usually able to generate good descriptions, but not in this particular case. We can solve this problem in two ways. The first one is calling desc inside our generator:

var util = require('util'),
    yeoman = require('../../../');

module.exports = Generator;

function Generator() {
  yeoman.generators.Base.apply(this, arguments);

  this.desc('This generator creates an initializer file at app/js/');

util.inherits(Generator, yeoman.generators.Base);

Generator.prototype.createInitializerFile = function() {
  this.write('app/js/initializer.js', "// Add initialization content here");

Now we can see the new description by invoking --help on the new generator. The second way to add a description is by creating a file named USAGE in the same directory as our generator. We are going to do that in the next step.

Creating Generators with Generators

Generators themselves have a generator:

$ yeoman init generator initializer
  create  lib/generators/initializer
  create  lib/generators/initializer/index.js
  create  lib/generators/initializer/USAGE
  create  lib/generators/initializer/templates

This is the generator just created:

var util = require('util'),
    yeoman = require('../../../');

module.exports = Generator;

function Generator() {
  yeoman.generators.NamedBase.apply(this, arguments);

  this.sourceRoot(__dirname, 'templates');

util.inherits(Generator, yeoman.generatos.NamedBase);

First, notice that we are inheriting from yeoman.Generators.NamedBase instead of yeoman.Generators.Base. This means that our generator expects at least one argument, which will be the name of the initializer, and will be available in our code in the variable name.

We can see that by invoking the description of this new generator:

$ yeoman init initializer --help

  yeoman init initializer NAME [options]

Note: The banner is not automatically generated yet for generators (the Usage: thing above). Same for options and arguments defined by the generator, they should show up during the help output. Right now, the USAGE file is dumped to the console as is.

We can also see that our new generator has an instance method called sourceRoot.

This method points to where our generator templates will be placed, if any, and by default it points to the created directory lib/generators/initializer/templates (so the sourceRoot(__dirname, 'templates') can be removed, this is the default).

In order to understand what a generator template means, let’s create the file lib/generators/initializer/templates/initializer.js with the following content:

// Add initialization content here

And now let’s change the generator to copy this template when invoked:

var util = require('util'),
    yeoman = require('yeoman');

module.exports = Generator;

function Generator() {
  yeoman.generators.NamedBase.apply(this, arguments);
  // if your templates/ location differ, feel free to set it with sourceRoot()

util.inherits(Generator, yeoman.generatos.NamedBase);

Generator.prototype.copyInitializerFile = function() {
  this.copy('initializer.js', 'config/initializers/' + + '.js');

And let’s execute our generator:

$ yeoman init initializer core_extensions

We can see that now an initializer named core_extensions was created at config/initializers/core_extensions.js with the contents of our template. That means that copy copied a file in our source root to the destination path we gave. The property name is automatically created when we inherit from yeoman.Generators.NamedBase, and match the value of the given argument (NamedBase automatically specify an argument via this.argument)

Generators Lookup

When you run yeoman init initializer core_extensions yeoman requires these paths in turn until one is found:


Note: index.js may be anything else, as long the module entry point is defined in a package.json.

Second Note: While true, the help output might miss a generator. It looks for file below lib/generators at few locations, searching for index.js files.

yeoman will do this lookup at few different places, in this order:

  • relative to the working directory, from within a yeoman application.
  • relative to any node_modules/yeoman-* module. These are called "yeoman plugins", they should package up their generator in the lib/generators directory.

This mean that users may override part or the whole set of generator used by yeoman, either at an application level, with custom handcrafted generator or via "yeoman plugin" (a node package that defines a set of generators in their lib/generators directory).

If none is found you get an error message.

Customizing your Workflow

Yeoman own generators are flexible enough to let you customize scaffolding. They can be configured in your application Gruntfile, these are some defaults:

  generators: {
    'template-engine': 'handlebars',
    'test-framework': {
      name: 'mocha',
      options: {
        ui: 'bdd'

Looking at this output, it’s easy to understand how generators work in yeoman.

Generator relies on hook and other generators, some don't actually generate anything, they just invokes others to do the work.

This allows us to add/replace/remove any of those invocations. For instance, the controller generator invokes the view and test-framework hooks. These hooks tries to resolve their value from cli options first, then look at the Gruntfile for a generator property with the corresponding hook name, and finally defaults to the hook name if none were found.

Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication.

TBD Finish up this section: example of running controller generator, see the hooks. etc.

Customizing Your Workflow by Changing Generators Templates

In the step above we simply wanted to add a line to the generated helper, without adding any extra functionality. There is a simpler way to do that, and it’s by replacing the templates of already existing generators, in that case yeoman.generators.HelperGenerator.

Generators don’t just look in the source root for templates, they also search for templates in other paths. And one of them is lib/templates. Since we want to customize yeoman.generators.HelperGenerator, we can do that by simply making a template copy inside lib/templates/yeoman/helper with the name helper.js.

If you generate another resource, you can see that we get exactly the same result! This is useful if you want to customize your scaffold templates and/or layout by just creating edit.html.erb, index.html.erb and so on inside lib/templates/erb/scaffold.

More On Generators

So we know that a typical generator looks like the following:

{% highlight js %} var util = require('util'), yeoman = require('../../../');

module.exports = Generator;

function Generator() { yeoman.generators.NamedBase.apply(this, arguments); }

util.inherits(Generator, yeoman.generators.NamedBase);

Generator.prototype.createSomething = function() { // code };

// ... other methods ... {% endhighlight %}

Generators can also be written in CoffeeScript, they just needs to be named with a .coffee extension (typically lib/generators/generatorName/

{% highlight coffee %} yeoman = require 'yeoman'

module.exports = class Generator extends yeoman.generators.NamedBase

constructor: (args, options, config) -> super args, options, config

createSomething: -> # code

# ... other method ... {% endhighlight %}

They're usually layout like so:

└── generators
    └── generatorName
        ├── USAGE
        ├── index.js
        └── templates

Generators extends either yeoman.generators.Base or yeoman.generators.NamedBase. NamedBase is suitable to use for generators that expects a "name" argument, such as yeoman init model [NAME].

Every public method in a generator are executed serially. Every first level method in the prototype chain, eg. inherited method in Base are not.

Two exceptions:

  • any method beginning with _ is not ran, you may use them as method helper. They won't be called automatically on generator invocation.
  • a constructor method, most likely when using CoffeeScript to implement the generator

Either Name or BasedName are EventEmitters, you may use the EventEmitter API if you wish to (emit / on / once / ...)


Generators get mixed into their prototype the grunt.file API. You can use read, readJSON, write, copy, mkdir, expandFiles, etc.

Note that some of them have special additional logic attached, for copy, read and write.

copy and read make sure to prefix the source filename to be within the generator's source root (usually a templates/ folder next to the generator implementation).


In addition to the grunt.file API directly available into your generators, you can use the grunt.log API as this.log

{% highlight js %} Generator.prototype.doingSomething = function() { this.log.writeln("I\m doing something"); this.log.ok(".. And I think it's ok .."); }; {% endhighlight %}

sync vs async

Methods are expected to run synchronously by default. This is fine for most cases, and will be just what you need for most common operations. Every file system method (copy, write, read, etc.) available are borrowed to grunt's, where most of them are implemented synchronously for conveniency.

If you wish to run your method in an asynchronous way, you should tell the system to do so. Very similarly to how you would handle async stuff in grunt tasks.

If a method is asynchronous, this.async must be invoked to tell the system to wait. It returns a handle to a "done" function that should be called when the method has completed. Every non-falsy value (most likely an Error object) can be passed to the done function as a first argument to indicate a failure.

It this method isn't invoked, the method executes synchronously.

Generator methods

The following are methods available for generators.

NOTE: Methods provided by Grunt are not covered this guide and can be found in "Grunt's documentation":


Base Generator

A Base generator has the following methods, members, and events.


A hash object holding all cli parsed options by nopt.

generator.argument(name, options)

Adds an argument to the class and creates an instance property for it.

Arguments are different from options in several aspects. The first one is how they are parsed from the command line, arguments are retrieved from position:

yeoman init NAME

Instead of:

yeoman init --name NAME

Besides, arguments are used inside your code as a property (this.argument), while options are all kept in a hash (this.options).


  • desc - Description for the argument.
  • required - If the argument is required or not.
  • optional - If the argument is optional or not.
  • type - The type of the argument, can be String, Number, Array, Object (in which case considered as an Hash object, key:value).
  • defaults - Default value for this argument. It cannot be required and have default values.
  • banner - String to show on usage notes.

generator.option(name, options)

Adds an option to the set of generator expected options, only used to generate generator usage. By default, generators get all the cli option parsed by nopt as a this.options Hash object.

  • name - The name of the argument
  • options - Hash of configuration values where:
  • desc - Description for the argument.
  • type - Type for this argument, either Boolean, String or Number.
  • defaults - Default value for this argument.
  • banner - String to show on usage notes.
  • hide - If you want to hide this option from the help.


Stores and return the source root for this class. This is used with copy(), template(), read(), etc. to prefix the relative path.

By default, takes the value of templates/ next to the generator file.

When no path is given, returns the value of _sourceRoot.


Sets the destination root for this class, ensure the directory is created and cd into it.

generator.hookFor(name, options)

Must be called within the constructor only.

Register a hook to invoke a generator based on the value supplied by the user to the given option named "name". An option is created when this method is invoked and you can set a hash to customize it.

{% highlight js %} function MyGenerator(args, options, config) { yeoman.generators.Base.apply(this, arguments); // init a framework specific controller this.hookFor('js-framework'); } {% endhighlight %}

Hooks work in a way that you can delegate the groundwork of scaffolding to other generators. They're totally inspired by Rails 3 generators hook_for method.

The example above will create a js framework option and will invoke a generator based on the user supplied value.

For example, if the user invokes the controller generator as:

yeoman init controller Account --js-framework backbone

The controller generator will then try to invoke the following generators:

"backbone:controller" "backbone"

Notice that the value of a given hook can be defined in your application Gruntfile as well:

{% highlight js %} // grunt config generators: { 'js-framework': 'backbone' } // ... more grunt config ... {% endhighlight %}

This is what allows any js framework to hook into Yeoman as long as it provides any of the hooks above.


The first and last part used to find the generator to be invoked are guessed based on constructor's hookFor invokes, as noticed in the example above. This can be customized with the following options:

  • as - the context to lookup, defaults to generator's name.
  • args - arguments to pass through, defaults generator's arguments.
  • options - options to pass through, defaults to generator's options.
  • config - Grunt config to pass through, defaults to generator's config.

Let’s suppose you are creating a generator that needs to invoke the controller generator from a unit test. Your first attempt is:

{% highlight js %} // in lib/generators/awesome/index.js generator's constructor. this.hookFor('test-framework'); {% endhighlight %}

The lookup in this case for test_unit as input is:

"test_framework:awesome", "test_framework"

(more specifically, "jasmine:awesome", jasmine" which is the default value for test-framework hook)

Which is not the desired lookup. You can change it by providing the as option:

{% highlight js %} // in lib/generators/awesome/index.js generator's constructor. this.hookFor('test-framework', { as: 'controller' }); {% endhighlight %} And now it will lookup at:

"test_framework:controller", "test_framework"

generator.copy(source, destination, options)

Copy a source file to a destination path, creating intermediate directories if necessary.

Grunt's grunt.file.copy is used, we simply make sure that relative path are prefixed by the generator's sourceRoot value.

{% highlight js %} // similar to var source = path.join(this.sourceRoot(), 'path/to/file.js'); grunt.file.copy(source, destination, options); {% endhighlight %}, [encoding])

Same as copy, .read() relative filepath are prefixed by self.sourceRoot() value.

generator.write(filepath, [encoding])

Write the specified contents to a file, creating intermediate directories if necessary.

Just like grunt.file.write, we simply ensure the log output of the files being written.

{% highlight js %} // similar to grunt.option('verbose', true); grunt.file.write(filepath, encoding); grunt.option('verbose', false); {% endhighlight %}

generator.template(source, [destination], [data])

Gets an underscore template at the relative source, executes it and makes a copy at the relative destination. If the destination is not given it's assumed to be equal to the source relative to destination.

{% highlight js %} this.template('Gruntfile.js'); {% endhighlight %}

will copy and process the templates/Gruntfile.js file through grunt.template.process, and write the results to ./Gruntfile.js relative the the application root.

Another example is using a templates/model.js template to write at the app/js/models/{name}-model.js location in a NamedBase generator.

{% highlight js %} this.template('model.js', path.join('app/js/models', + '-model.js')); {% endhighlight %}, [destination])

Copies recursively the files from source directory to destination root directory. If the destination is not given it's assumed to be equal to the source relative to destination.

Each file is copied and processed through grunt.template.process.

{% highlight js %}'.', 'test'); {% endhighlight %}

The example above copies and process any files within generators templates/ directory, and write them at the test/ location.

generator.tarball(url, destination, cb)

Fetch a remote tarball, and untar at the given destination.

{% highlight js %} this.tarball('', 'vendor/bootstrap', this.async()); {% endhighlight %}

generator.fetch(url, destination, cb)

Download a single file at the given destination.

{% highlight js %} this.fetch('', 'js/vendor/zepto.js', this.async()); {% endhighlight %}

generator.remote(username, repository, [branch], cb)

Remotely fetch a package on github, store this into an internal _cache/ folder, and invokes provided callback on completion with a "remote" object as the main API to interact with downloaded package.

  • username - GitHub username
  • repository - GitHub repository to fetch from
  • branch - Optional branch or sha1, defaults to master
  • cb - function to invoke on completion

The example below downloads and cache the html5-boilerplate project, and use the remote object to copy the whole project into the app/ folder.

{% highlight js %} var cb = this.async(); this.remote('h5bp', 'html5-boilerplate', 'master', function(err, remote) { if(err) return cb(err); // remote.copy('index.html', 'index.html'); // remote.template('index.html', 'will/be/templated/at/index.html');'.', 'app'); cb(); }); {% endhighlight %}

remote() allows the download of full repositories and copying of single or multiple files. remote object is your API to access this fetched (and cached) package and copy / process files.

remote.copy(source, destination, options)

Same as generator.copy() but relative source is prefixed with the cache directory.

remote.template(source, destination, options)

Same as generator.temlate() but relative source is prefixed with the cache directory.

remote.template(source, destination, options)

Same as but relative source is prefixed with the cache directory.

Prompt user before overwriting files with --force

Generators also support a warnOn method, which allows developers to warn on global paths that are matching those paths or files which the generator is going to generate (e.g self.warnOn('*').

Where used, Yeoman will warn the user they if they proceed that a file will be overwritten and they may need to call the generator with the --force flag to proceed.

warnOn is most likely to be used in constructors.

Jump to Line
Something went wrong with that request. Please try again.