Introduction

In the previous article we’ve built a REST API for a voting application using sequelize. In this article we will consume this API and build the front end using emberjs. We also mentioned about, generator-emberfs, a yeoman generator for fullstack applications using emberjs and express, that we used to scaffold our application.

The voting application will be where users can vote for a poll and see the results of the poll. You can see a live example here.

Scaffold Ember Application

In the previous article we used generator-emberfs for server side, we will continue using it for client side as well. It supports scaffolding, asset compilation, optimization for production, live reloading and test driven development. It uses gulp for build system.

You can launch the server and listen for changes using the command:

gulp devserver

Or you can build and optimize your application for production:

gulp build

Directory Structure

This is our directory structure for client side. vendor folder contains third party libraries, templates folder contains handlebars templates, styles folder contains css styles in sass, scripts folder contains the emberjs application code.

app/client
|-- scripts
|   |-- app.js
|   |-- common.js
|   |-- components
|   |   `-- progress-bar.js
|   |-- controllers
|   |   `-- index_controller.js
|   |-- main.js
|   |-- mixins
|   |-- models
|   |   `-- poll_model.js
|   |-- router.js
|   |-- routes
|   |   `-- index_route.js
|   `-- views
|-- styles
|   `-- style.scss
|-- templates
|   `-- components
`-- vendor

Note that this folder structure is boilerplate for the generator-emberfs. It uses requirejs with AMD modules. But, yet we won’t get into details of requirejs in this article, rather stick to essential codes for emberjs.

Routes in Ember

We won’t define any particular route for this simple application. Rather we will use the default IndexRoute Ember provides.

App.Router.map(function() {
});

App.router.reopen({
  location: 'history'
});

Our IndexRoute will have the poll #1 as its model. Remember we have provided a seed model as the poll #1 in sequelize, in the previous article.

App.IndexRoute = Ember.Route.extend({
  model: function() {
    // GET api/v1/polls/1
    return this.store.find('poll', 1);
  }
});

this.store uses ember-data to pull the models. It uses an adapter, which is in our case a DS.RESTAdapter. So this code will make a request to api/v1/polls/1 to build a model. Later we can use the model in our controller and templates.

Templates in Handlebars

Let’s drop a skeleton template using bootstrap for style and handlebars for bindings. I will use emblem formatting just for efficient view.

File: templates/index.hbs

Here, we have a ` binding, main header for the poll. and onediv binding for showing the poll choices and allowing vote. and adiv ` binding for showing the poll results.

In the poll results we use a, progress-bar text=text percent=vote-percent, ember component to display the results, which we will mention later.

Finally we have various actions for communicating with the model click="showResults", and click="vote id". These actions are handled in ember controller and will be discussed later.

Models in Ember Data

Just as we defined data models for sequelize, we will define the same models for emberjs using ember-data. We will use ember-data DS.RESTAdapter for communicating with the REST API.

In the previous article We mentioned about our three models Poll, Choice, and Vote and the relationships between them. Here we define the same relationships using ember-data.

File: models/poll_model.js

App.Poll = DS.Model.extend({
    question: DS.attr('string'),
    choices: DS.hasMany('choice')
  });

  App.Choice = DS.Model.extend({
    text: DS.attr('string'),
    description: DS.attr('string'),
    count: DS.attr('number'),
    votes: DS.hasMany('vote'),
    poll: DS.belongsTo('poll')
  });

  App.Vote = DS.Model.extend({
    choice: DS.belongsTo('choice')
  });

Note that ember uses DS.attr for defining attributes, and DS.hasMany, DS.belongsTo methods for defining relationships.

If you visit /api/v1/polls/1 in your local server, you will see the json response for the poll #1:

{"poll":{
  "id":1,
  "question":"What features would you like to see",
  "choices":[{
    "id":1,
    "text":"Improved UI",
    "description":"New, fancy interface",
    "PollId":1,
    "count":0},{
    "id":2,
    "text":"Improved Performance",
    "description":"Faster response times",
    "PollId":1,
    "count":0
    }]
}}

Notice choices attribute is embedded within the poll model. Normally ember-data expects this to be side loaded. So we will have to use DS.EmbeddedRecordsMixin to enable ember-data to parse our embedded response.

App.PollSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
  attrs: {
    choices: { embedded: 'always' }
  }
});

Controllers in Ember

We will extend the default IndexController in our application. In ember, controllers communicate between the template and the model the extra properties defined in controller will be also available to the template. So ember controllers is in a way model decorators.

Controller Computed Properties (Model Decorators)

IndexController extends Ember.ObjectController and decorates the poll model. We have various computed properties that will be available to our template, and they will be live bounded to our model.

File scripts/controllers/index_controller.js

App.IndexController = Ember.ObjectController.extend({
  resultsHidden: true,
  
  pollChoices: function() {
    var choices = this.get('model.choices');
    
    var totalVotes = this.get('totalVotes');

    choices.map(function(item) {
      var votePercent = (item.get('count') / totalVotes) * 100;
      item.set('vote-percent', votePercent.toFixed(2));
      return item;
    });
    return choices;
  }.property('model.choices'),

  totalVotes: function() {
    var choices = this.get('model.choices');

    var totalVotes = choices.reduce(function(prev, item) {
      return prev + item.get('count');
    }, 0);

    return totalVotes;
  }.property('model.choices'),

  // ...
});

resultsHidden property toggles between poll results and voting. pollChoices computed property computes the total percentage of votes for each choice. totalVotes computed property computes the total number of votes for a poll. Note that .property('model.choices') function that is appended to computed property methods. That binds the model.choices to our computed property so whenever a change occurs computed property updates live.

Controller Actions

Controller also communicates between template and model by means of actions. Remember we had three actions in our template, we handle those actions inside our controller.

File: scripts/controllers/index_controller.js

actions: {
    showResults: function() {
      this.get('model').reload().then(function() {
        this.set('resultsHidden', false);
      }.bind(this));
    },
    hideResults: function() {
      this.set('resultsHidden', true);
    },

    vote: function(choiceId) {
      var choices = this.get('model.choices');

      var vote = this.store.createRecord('vote', {
        choice: choices.findBy('id', '' + choiceId)
      });

      var self = this;

      vote.save().then(function(vote) {
        self.send('showResults');
      }, function(vote) {
        self.send('showResults');
      });
    }
  }

showResults action toggles the resultsHidden property to false so the results are shown. Note that before showing the results, it reloads the model so we get the latest results. hideResults is the opposite, it goes back to the voting view. vote action is where the user votes. It takes a choiceId parameter that is the poll choice. We create a new vote record and save it.

Progress Bar Ember Component

Now let’s see how we define an ember component. In our case a progress bar for displaying the percentage of votes for a poll choice.

First we define a template for our ember component.

File: templates/components/progress-bar.hbs

Next we define the code for our ember component.

File: scripts/components/progress-bar.js

App.ProgressBarComponent = Ember.Component.extend({
  'progress-bar-type': function() {
    var barTypes = [
      'progress-bar-danger',
      'progress-bar-warning',
      'progress-bar-info',
      'progress-bar-success'
    ];
    
    var percent = Math.min(this.get('percent'), 100);
    var barType = barTypes[Math.floor((percent - 1) / 25)];

    return barType;
  }.property('percent'),

  'percent-style': function() {
    return 'width:' + this.get('percent') + '%';
  }.property('percent')
});

Here, we calculate progress-bar-type based on percentage, that will apply the bootstrap classes to the div and make the progress bar change colors with the percentage.

Setup the Ember Application

Finally we start our ember application and extend our ember application adapter.

var App = Ember.Application.create();

App.ApplicationAdapter = DS.RESTAdapter.extend({
  namespace: 'api/v1'
});

Note that extend the DS.RESTAdapter and we provide a namespace option to tell it that our REST API resides at api/v1 namespace.

Development and Production

You can use gulp test to run your client side tests. generator-emberfs uses coffeescript for test code. You can use ember-qunit for unit testing and ember test-helpers for integration tests. It uses testem as the test runner. But, yet since we are using a server side REST API, You have to provide an API Proxy configuration to testem to redirect your API calls to your server, and launch your server before running the tests.

At this point we have finished the application and it’s ready to ship. But first you need to build it using the command gulp build. This will compile all your assets, minify and optimize and concatenate your script and css files into the public directory. Now you can launch your server using the command: node config/app.

Conclusion

In this article we have built a front end for a REST API where users can vote for a poll and see the results of the poll using emberjs. We’ve built a template in handlebars, setup the models in ember-data, extended an ember controller and an ember component for displaying progress bars.

The full repository is at github. A live example is available here

Introduction

Sequelize is an ORM (Object Relational Mapper) for NodeJS that provides easy access to various databases like MySQL, MariaDB, SQLite, or PostgreSQL.

It has a nice website with helpful documentation and examples to get started. Also there is an IRC channel #sequelizejs on Freenode.

In this article we will build a voting application where users can vote for a poll and we will record their IP so they cannot vote twice. We will use sequelize to model our data and build a REST API. Later we will build the front end using emberjs.

Scaffold Voting Application

Since we are using emberjs we might use ember-cli for our project. But, yet recently I published a yeoman generator generator-emberfs for emberjs fullstack projects like the one we are building now. It does all the scaffolding for emberjs on the client side and expressjs on the server side. So we will use it for this article.

You can install using the command:

npm install -g generator-emberfs
  yo emberfs

Directory Structure

This is our directory structure for voting application. config folder contains the initial server code and configuration files. app/models, app/routes and app/views folders contain our server side models, routes, and views respectively. db folder is for the sqlite database file and code for our database seed.

.
|-- app
|   |-- models
|   |   |-- index.js
|   |   `-- poll.js
|   |-- routes
|   |-- `-- api.js
|   `-- views
|       `-- layouts
|-- config
|   |-- app.js
|   `-- server.js
|
`-- db
    |-- development.sqlite
    `-- seed.js

We will define only routes for the REST API so we won’t mention about the app/views folder here.

Note that this folder structure is boilerplate for the generator-emberfs. So you won’t need to do the tedious work if you use it.

Models in Sequelize

This is our model diagram. Poll is a question and has many Choices. Choice is a poll choice with a text and description and has many Votes. Vote has an ip that identifies the voter, so we can make sure one ip can vote only once.

image

All our models are in file app/models/poll.js. Later we will import them.

Vote model is simple, just a single field ip and has no relationships. It also has some helpers methods which I will mention later.

var Vote = sequelize.define('Vote', {
    ip: DataTypes.STRING
    // ... define model fields here
  }, {
    classMethods: {
      associate: function(models) {
        // define relationships here
      }
        // ... define class methods here
    }
  });

Choice model has two fields, text and description, and has one-to-many relationship with the Vote model. We define the relationships in a class method named associate.

var Choice = sequelize.define('Choice', {
    text: DataTypes.STRING,
    description: DataTypes.STRING
  }, {
    classMethods: {
      associate: function(models) {
        Choice.hasMany(models.Vote, { as : 'votes' });
      }
    }
  });

Poll model has one field question, and has one-to-many relationship with the Choice model.

var Poll = sequelize.define('Poll', {
    question: DataTypes.STRING
  }, {
    classMethods: {
      associate: function(models) {
        Poll.hasMany(models.Choice, { as: 'choices' });
      }
    }
  });

Import all models in Sequelize

Now we have defined our models, we need to import them with sequelize. We will do that in file app/models/index.js.

In our example we have only one file defining our models namely app/models/poll.js. But we can have more than that, and we will import all the files in app/models folder.

First let’s require our dependencies, and initialize Sequelize. votes-app-db is the name of our database.

We are using sqlite for the database and ./db/development.sqlite file for the database. sqlite is a zero-configuration, serverless database. It works directly from the database files on disk.

File: app/models/index.js

var fs = require('fs'),
  path = require('path'),
  lodash = require('lodash'),
  Sequelize = require('sequelize'),
  sequelize = null,
  db = {};

sequelize = new Sequelize('votes-app-db', null, null, {
  dialect: 'sqlite',
  storage: './db/development.sqlite'
});

Before we import the models, let’s see how we export our models in app/models/poll.js.

File: app/models/poll.js

var Sequelize = require('sequelize');

module.exports = function(sequelize, DataTypes) {
  // I omit the definitions.
  var Vote, Poll, Choice;

  return [Vote, Poll. Choice];
};

We export an array of our models. Now let’s import each file in app/models to sequelize.

File: app/models/index.js

fs.readdirSync(__dirname)
  .filter(function(file) {
    return (file.indexOf('.') !== 0) && (file !== 'index.js');
  })
  .forEach(function(file) {
    var model = sequelize.import(path.join(__dirname, file));
    if (model instanceof Array) {
      model.forEach(function(m) {
        db[m.name] = m;
      });
    } else {
      db[model.name] = model;
    }
  });

We filter out the index.js and import every file to sequelize. Later we keep references to our models in db object. Note that our model files can both return an array or a single object, that’s what the if condition is checking for.

Finally we call the associate class method for each model that will define the relationships between models. Then we export all the models (db object) along with sequelize.

Object.keys(db).forEach(function(modelName) {
  if ('associate' in db[modelName]) {
    db[modelName].associate(db);
  }
});

module.exports = lodash.extend({
  sequelize: sequelize,
  Sequelize: Sequelize
}, db);

Seed for the Database

Next, we seed the database a sample poll with two choices.

File: db/seed.js

module.exports = function(db) {

  db.Poll.create({
    question: 'What features would you like to see'
  }).success(function(poll) {
    db.Choice.bulkCreate([{
      id: 1,
      text: 'Improved UI',
      description: 'New, fancy interface',
      PollId: poll.id
    }, {
      id: 2,
      text: 'Improved Performance',
      description: 'Faster response times',
      PollId: poll.id
    }]);
  });

};

Note that each model has a create and bulkCreate function. The difference is create takes a single object and bulkCreate takes an array of objects.

One final thing is the choice model instances has an extra attribute, PollId, that is the foreign key referencing the Poll model.

Helper methods for Models

We will define two helper methods for the Vote model. They are both defined under the classMethods object (near to associate method).

findCount method takes a choiceId and finds the number of votes for that choice.

File: app/models/poll.js

findCount: function(choiceId, callback) {
    Vote.count({
      where: { 'ChoiceId': choiceId}
    }).success(function(count) {
      callback(null, count);
    });
  }

addVote method takes an ip and a choice and creates a new vote. The trick here is that we have to make sure the given ip doesn’t vote twice for the same poll. So we need a nifty sql statement to “select all the votes for the poll that the given choice belongs to and that is the same ip as the given ip”. This statement will return a single vote if the given ip has voted for the same poll or null if it hasn’t.

File: app/models/poll.js

addVote: function(ip, choice, callback) {
    // sequelize translation of the sql command:
    //
    // select * from votes, choices, polls where
    // votes.choiceId == choices.id and choices.pollId ==
    // polls.id and choices.id == choice polls.id in
    // (select pollId from votes, choices where
    // votes.choiceId == choices.id and votes.ip == ip)
                
    Poll.findAll({ where: Sequelize.and(
      {
        'choices.id': choice
      },
      {id: 
        { in:
          Sequelize.literal('select "Choices"."PollId" from "Votes", "Choices" where "Votes"."ChoiceId" = "Choices"."id" and "Votes"."ip" = \'' + ip + '\'')
        }
      }),
        include: [ {
          model: Choice, as: 'choices',
          include: [{ model: Vote, as: 'votes' }]}]
      }).success(function(votes) {
        if (!votes || votes.length === 0) {
          Vote.create({
            ip: ip,
            ChoiceId: choice
          })
            .success(function(vote) {
              callback(null, vote);
            });
        } else {
          callback("Vote already exists");
        }
      });
  },

I am sure there is a better way to build this statement in sequelize, but this works too. Note that we make use of Sequelize.literal method that interprets the raw sql command.

Finally upon success, if the vote already exists, we give error, otherwise we create a new vote which builds and saves the vote to the database.

Routes for Express 4

Routing in Express 4 is modular and mountable. A Router instance is a complete middleware. But, yet I won’t get into detail how to use express routers in this article. For more information check out the express docs and the migration guide.

All our API routes are in file app/routes/api.js.

/polls route lists all the available polls.

router.get('/polls', function(req, res) {
    db.Poll.findAll({
      // you can include choices for the poll, or not.
      //include: [{ model: db.Choice, as: 'choices' }]
    }).success(function(polls) {
      res.send({
        polls: polls
      });
    });
  });

Note that include option enables us to embed the choices for the poll. In our case we opt not to.

/polls/:id route gets a single poll with a given id. This time we include the choices for the poll as well. The trick here is for each choice we find the number of votes for that choice, and include the count in the choice model using the setDataValue method.

router.get('/polls/:id', function(req, res) {

    db.Poll.find({
      where: { id: req.params.id },
      include: [{model: db.Choice, as: 'choices' }]
    }).success(function(poll) {
      async.map(poll.choices, function(choice, callback) {
        db.Vote.findCount(choice.id, function(err, count) {
          choice.setDataValue('count', count);
          callback(err, choice);
        });
      }, function(err, results) {
        poll.setDataValue('choices', results);
        res.send({
          poll: poll
        });
      });
    });
  });

Note that we use async library to map poll.choices and add the vote count for each choice. Later we use setDataValue method for the poll model to set the choices to the map results.

We post to /votes route to make a vote. One ip can vote for a poll only once, thanks to our addVote helper method.

router.post('/votes', function(req, res) {
    var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    // randomize the ip to test your app
    //ip = Math.random();
        
    var choice = req.body.vote.choice;
        
    db.Vote.addVote(ip, choice, function(err, vote) {
      if (err) {
        res.send(err);
      } else {
        res.send(vote);
      }
    });
  });

Note that we use x-forwarded-for header or the req.connection.remoteAddress to get the ip. If you want to test the application so you can have many votes, randomize the ip with Math.random.

Finally /votes/:choiceId route will return the number of votes for a given choice.

router.get('/votes/:choiceId', function(req, res) {
    var choice = req.params.choiceId;

    db.Vote.findCount(choice, function(err, count) {
      if (err) {
        res.send(err);
      } else {
        res.send({ vote: count });
      }
    });
  });

Setup the Server

Finally we start sequelize, seed the database, and fire up the express server.

File: app/config/app.js

var app = require('./server'),
  db = require('../app/models');

db.sequelize
  .sync({ force: true})
  .complete(function(err) {
    if (err) {
      throw err[0];
    } else {
      // seed
      require('../db/seed')(db);
      
      app.listen(app.get('port'), function() {
        console.log('express listening on ' + app.get('port'));
      });
    }
  });

Note that we require ../app/models that exports all the models and sequelize as the db object. Also we require ./server that exports the express application. I won’t mention about configuring and setting up the express server, it’s simple enough and you should do it however you like. For more details check out the full repository at github.

Conclusion

In this article we have built a REST API using sequelize for voting polls. We’ve setup models in sequelize provided seed for the database, used query methods for the models, and setup the API routes for the express server. Next up we will build the front end using emberjs.

The full repository is at github.

Introduction

In the previous article we built a Phaser project template, that used gulp as a build tool. In this article we will build a yeoman generator, for scaffolding, generating boilerplate from that template. We will also use mocha to write tests and see how to do test driven development. Finally we will publish it to npm.

Initialize Yeoman Generator

A yeoman generator is an npm package, that runs on node environment. As we write our generator we will test it with mocha.

First install mocha with npm:

$ npm insall -g mocha

Next we initialize npm, and create our package.json file.

$ npm init

Next, we install our dependencies:

$ npm install --save yeoman-generator yosay chalk chai fs-extra gulp mocha

We also need yo as a peerDependency, you can see the example package.json as a reference, or just use it as is.

Next I’ve configured some utility modules, that are going to make our life easier, grab them as we will later use them. util.js, and test-util.js, place them in the root directory, next to package.json.

Directory Structure

Here’s the standard directory structure for yeoman generators.

.
|-- LICENSE
|-- README.md
|-- generators
|   |-- app
|   |   |-- templates
|   |   `-- index.js
|   |-- prefab
|   |   |-- templates
|   |   `-- index.js
|   `-- state
|       |-- templates
|       `-- index.js
|-- package.json
|-- test
|   |-- fixtures
|   |   |-- app.js
|   |   |-- bower.json
|   |   `-- package.json
|   |-- test-creation.js
|   |-- test-load.js
|   |-- test_prefab.js
|   `-- test_state.js
|-- test-util.js
`-- util.js

As you can see, besides LICENSE, README.md, package.json and utility files, we have two folders generators and test.

generators folder holds each sub-generator. Each folder is the same name as the sub-generator name. In our case we have a default generator app, that is called with command yo name, and two extra sub-generators prefab and state. Each sub-generator has an index.js file, that contains the entry point, and a templates folder that contains the template files for the boilerplate. Template files will use underscore templating library.

test folder holds the tests for the yeoman generator. test/fixtures folder holds fixture files that we need for some tests.

For now, create two folders generators and test, next we will write tests, and later write code to pass them.

Write Failing Test, Code, Pass Test

That’s how we develop our generator, using test driven development. Before we start, I want to tell you that we will write our tests in coffeescript. I never liked coffescript, until I found out the perfect opportunity to learn it, that is because it is more convenient for nested test code, you won’t have to deal with nested brackets. Now let’s write our first test.

Default Generator app

Default generator used when you call yo name. It is the app generator, and it resides in the app folder.

File: test/test-load.js

assert = require 'assert'

describe 'phaserjs generator', ->
  it 'can be imported', ->
    app = require '../generators/app'
    assert app != undefined

Here we use BDD interface that mocha provides, that is, describe, and it keywords. Mocha allows you to use any assertion library, we use assert module. describe defines a test suite, it defines a test case.

In our case we have a phaserjs generator test suite with a test that says it can be imported. In the test, we simply require our first generator, that is the main generator ../generators/app, and assert that it is defined.

Now when you go to the root directory and run your tests with command mocha, it will fail, because we don’t have an app generator yet, so let’s code our first generator.

Extending generator

Yeoman offers two base generators Base and NamedBase that we can extend from. For the default app generator we will extend Base generator.

File: generators/app/index.js

var path = require('path');
var chalk = require('chalk');


// Two utility modules that I provided before
var util = require('util');
var genUtils = require('../../util.js');

// modules yeoman provides
var yeoman = require('yeoman-generator');
var yosay = require('yosay');

var PhaserGenerator = yeoman.generators.Base.extend({

});

module.exports = PhaserGenerator;

Here we extended the Base generator, and exported it as a module. Now the tests will pass.

But the generator doesn’t do anything yet, now let’s write some tests that asserts that our default generator actually creates some boilerplate.

File: test/test-creation.js

path = require 'path'
fs = require 'fs-extra'
exec = require('child_process').exec

helpers = require('yeoman-generator').test
expect = require ('chai').expect

describe 'phaserjs generator', ->

  beforeEach (done) ->
    @app = helpers
      .run path.join(__dirname, '../generators/app')
      .inDir path.join(__dirname, '.tmp'), (dir) ->
      
        fs.symlinkSync path.join(__dirname, 'fixtures/node_modules'),
            path.join(dir, 'node_modules'), 'dir'

        fs.mkdirpSync path.join(dir, 'app/')

        // bower_components
        fs.symlinkSync path.join(__dirname, 'fixtures/bower_components'), path.join(dir, 'app/bower_components'), 'dir'

        done()

  describe 'running app', ->
    describe 'with default options', ->
      it 'should pass jshint', (done) ->
        @app.withPrompt({})
            .on 'end', ->
              console.log 'running jshint'
              exec 'gulp jshint', (error, stdout, stderr) ->
                if (error)
                  console.log 'Error: ' + error
                  
                expect(stdout).to.contain 'Finished \'jshint\''
                expect(stdout).to.not.contain 'problems'
                done();

First, we require helpers module, that yeoman provides as test helpers, and chai assertion library. Then we have a beforeEach block that runs before every test within the test suite. Before every test we have to run the generator, and then run our tests against the end results.

The way we run the generator is simple, thanks to helpers module. we provide our generator path to the helpers.run method. This will return a RunContext on which you can later setup directory, mock prompt, options etc.

After running our generator with helpers.run method, we use inDir method to setup the directory to run the generator from. We pass it a .tmp directory. The second parameter is a callback we use to setup the .tmp directory. In our case we symlink node_modules and bower_components we had in our test/fixtures folder beforehand, so we don’t have to run npm install for our test scenario each time we test our generator.

The test will run gulp jshint and expect that it will finish with no problems.

To pass the test we need to generate the boilerplate Phaser project. Let’s see how we do that next.

File: generators/app/index.js

var PhaserGenerator = yeoman.generators.Base.extend({

  info: function() {
    this.log(this.yeoman);
    this.log(chalk.yellow(
      'Out of the box I create a Phaser app with RequireJS,\n' +
      'and gulp to build your app.\n'
    ));
  },

  generateBasic: function() {
        
    this.template('gitignore', '.gitignore');
    this.copy('jshintrc', '.jshintrc');
    this.copy('bowerrc', '.bowerrc');
    this.template('_package.json', 'package.json');
    this.copy('_bower.json', 'bower.json');
    this.template('_gulpfile.js', 'gulpfile.js');
  },

  generateClient: function() {
    this.sourceRoot(path.join(__dirname, 'templates'));
    
    genUtils.processDirectory(this, 'app', 'app');
    genUtils.processDirectory(this, 'build', 'build');
  },
    
  end: function() {
    this.installDependencies({
      skipInstall: this.options['skip-install']
    });
  }
});

Every method we added is called in sequence. First in the info method we display some ASCII art and info about our generator. Next in the generateBasic and generateClient methods we setup the boilerplate. And finally in the end method we run installDependencies method that runs bower install && npm install for us.

Note that there are three helper methods for copying files to setup the boilerplate. this.copy will simply copy the file from generators/app/templates folder to the users project folder, this.template will run the template engine, underscore, and copy the file. Finally we use genUtils.processDirectory that I added as a helper method that copies whole directories.

After coding our generator, we actually need template files to copy. They live in the generators/app/templates folder. Let’s take a look at _package.json template and how we use underscore to customize the boilerplate files.

File: generators/app/templates/_package.json

{
  "name": "<%= _.slugify(name) %>",
  "version": "0.0.0",
  "description": "Phaser template with requirejs and gulp",
  // ... rest is omitted
}

Here we use underscore templating, and helpers function to customize the name of the package. name variable is the name of the users project.

If you run the tests again, hopefully it will pass this time.

Sub Generator state

Sub generator state used when you call yo name:state. It is the state generator, and it resides in the state folder.

File: test/test_prefab.js

describe('phaserjs:prefab generator', ->
  defaultArgs = ['TestPrefab']

  beforeEach ->
    @app_prefab = helpers
      .run path.join(__dirname, '../generators/prefab')
      .inDir path.join(__dirname, '.tmp')

  describe 'with default options' ->
    it 'should generate expected files', (done) ->
      @app_prefab
        .withArguments {}
        .on 'end', ->
          assert.file ['app/scripts/prefabs/testprefab.js']

          assert.fileContent 'app/scripts/prefabs/testprefab.js', / function Testprefab\(game, x, y\) \{\n[\s\S]+Phaser\.Sprite\.call\(this, game, x, y, \'atlasname\', 0/

          assert.fileContent 'app/scripts/prefabs/testprefab.js', /Testprefab\.prototype = Object\.create\(Phaser\.Sprite\.prototype\)\;\n/
          
          assert.fileContent 'app/scripts/prefabs/testprefab.js', /Testprefab\.prototype.constructor = Testprefab;\n/

          done()

  describe 'with --group option', ->
    it 'should generate expected files', (done) ->
      @app_prefab.withOptions {'group':true}
                 .on 'end', ->

                   assert.fileContent 'app/scripts/prefabs/testprefab.js', / function Testprefab\(game, parent\) \{\n[\s\S]+Phaser\.Group\.call\(this, game, parent\)\;\n/

                   assert.fileContent 'app/scripts/prefabs/testprefab.js', /Testprefab\.prototype.constructor = Testprefab;\n/

                   done();

In this test suite, we have two tests, one uses the default options, second runs the generator with --group option. In each case we use assert.fileContent test helper to match a regex against the generated file.

To pass the test let’s code our sub generator.

File: generators/prefab/index.js

var PhaserJsStateGenerator = yeoman.generators.NamedBase.extend({
  init: function () {
    this.option('group', {
      desc: 'extend Phaser.Group',
      type: Boolean,
      defaults: false
    });
  },

  generate: function() {
    var slugName = this._.slugify(this.name),
        templateFile = 'prefab.js';
        
    if (this.options['group']) {
      templateFile = 'prefab_group.js';
    }
    this.template(templateFile, 'app/scripts/prefabs/' + slugName + '.js');
  }
});

Here we define an extra option group that can be passed to our sub generator. It defaults to false, you can enable it by calling the sub generator with group option $ yo name:prefab --group. In our case we use the option to decide which template we copy as boilerplate.

Manually Test Your Generator

Now your generator is passing all the tests, yet you want to see it in action. Since you’re developing the generator locally, and haven’t published it yet, you have to symlink your local module as a global module, using npm.

Run this command in your generators root directory.

$ npm link

Now you can call yo generator-name and test your generator if it works.

Publish Your Generator

Finally you can publish your generator. First create an account on npm. Next set your npm author info.

$ npm set init.author.name "Your Name"
$ npm set init.author.email "Your Email"
$ npm set init.author.url "Your Website"

$ npm adduser

Then publish with.

$ npm publish

A note about the package.json format

There is a list of yeoman generators in the official yeoman website. It is automatically pulled from the npm API. To list your generator there you need to add yeoman-generator keyword to your package.json.

{
  "name": "generator-phaserjs",
  "version": "0.1.0",
  "description": "Yeoman generator for Phaser with RequireJS",
  "repository": "eguneys/generator-phaserjs",
  "author": {
    "name": "Emre Guneyler",
    "email": "eguneys@hotmail.com",
    "url": "https://github.com/eguneys"
  },
  "keywords": [
    "yeoman-generator",
    "scaffold",
    "generator",
    "framework",
    "mvc",
    "phaser",
    "gulp",
    "requirejs"
  ],
  //.. rest is omitted
}

Before you publish remember these notes; set your package name properly, set a version number and bump it with every publish, set a description, set a github repository url, set your author details, set your keywords properly, and add a yeoman-generator keyword. Note that the repository field should fit either of these formats or it won’t get listed in the yeoman website, "repository": "eguneys/generator-phaserjs", "repository": "git://github.com/eguneys/generator-phaserjs".

Conclusion

In this article we have built a yeoman generator for Phaser using test driven development with mocha. We have learned how to write tests using BDD syntax, and use yeoman test helpers to ease testing, how to write yeoman generators using the yeoman generator API. Finally we have learned how to manually test our generator and publish it as a global npm module. You can find the full source code at github. Note that you should always search similar generators and see their source code before you write your own and I recommend using our approach and building your project template first, as we did in the first article, then writing your generator will be greatly simplified.

There are more that we haven’t covered you can do with yeoman API, such as user interaction, composability, storing user configuration and much more. For more information see the official yeoman website and these useful links.

Introduction

Yeoman is a project scaffolding tool, it defines your work-flow, and scaffolds the boilerplate. Gulp is a build system, alternative to grunt, it is stream based, and prefers code over configuration.

In this two series articles we will learn how to build a yeoman generator from scratch, using test driven development. for Phaser game projects, which I before introduced in my previous article. We will use gulp as our build tool and requirejs for module loader.

First step towards a yeoman generator, is building a project template. yeoman is only responsible for scaffolding. The rest is building the project with gulp and having a project template. In this article we will build our project template using gulp and requirejs, in the next article we will introduce yeoman, and start test driven development.

Initialize Phaser Game Project

The Phaser is a game framework that runs on browser, as we develop our game, we will run the game on the browser and live reload the changes. We will use npm for our development dependencies, and bower for the front end dependencies.

First we initialize npm.

$ npm init

This will ask various questions and create a package.json file for us.

Next we initialize bower the same way, and create a bower.json file.

bower init

Decide a directory structure

The next step is to decide a directory structure for the project.

.
|-- app
|   |-- data
|   |-- index.html
|   `-- scripts
|       |-- app.js
|       |-- common.js
|       |-- config.js
|       |-- lib_main.js
|       |-- main.js
|       |-- prefabs
|       `-- states
|           |-- boot.js
|           `-- preload.js
|-- bower.json
|-- build
|   |-- wrap.end
|   `-- wrap.start
|-- gulpfile.js
`-- package.json

app folder is where our application code resides. build folder is for files used by requirejs optimizer. We have our package.json, bower.json and gulpfile.js. The project will compile into public directory as we will see later.

Configure bower and jshint

npm will install it’s dependencies in the node_modules folder, and bower will install it’s dependencies in the bower_components folder, but, yet we can configure the default directory for bower using a .bowerrc

Create a .bowerrc file and add these in.

File: .bowerrc

{
  "directory": "app/bower_components"
}

Next, create a .jshintrc file. and setup your configuration.

Finally install the bower dependencies and save them in the bower.json.

$ bower install requirejs almond phaser --save

Note we use --save flag to make our changes saved in bower.json. We have three dependencies, requirejs the module loader, almond that we discussed in the previous article about requirejs, and Phaser the game framework.

gulp.js, The streaming build system

We have three types of tasks that gulp can help us for our project. Building the project, linting, and injecting code to our project, that is injecting our bower dependencies to our requirejs configuration file, and serving the project and watching for changes.

We will use gulp plugins and other npm modules to help us, the first plugin we use is gulp-load-plugins, that automatically loads any gulp plugins we have in our package.json, that is convenient.

var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var rimraf = require('rimraf');
var runSequence = require('run-sequence');

Note that we assign gulp-load-plugins to $, that is all the plugins are attached to. We also require two other npm modules, rimraf for removing files/folders, and runSequence for running gulp tasks in sync. Because gulp runs tasks asynchronously by default.

gulp; build the project!

First task is simple, clean, that will remove the build folder.

gulp.task('clean', function(cb) {
  rimraf(paths.dist, cb);
});

This is how you define a gulp task. notice we pass cb as a parameter, that makes the gulp task asynchronous. It will be called once the task is done and tell gulp to continue with the other tasks. By default gulp will run all the tasks and wait for nothing.

Next task is building the extra files in the app directory. In our case it’s index.html, you might have extra favicon.ico or robots.txt.

gulp.task('build-extras', function() {
  gulp.src('app/*.*')
      .pipe(gulp.dest('public'));
});

gulp.src takes a glob and represents a file structure, which then can be piped to plugins. gulp.dest can be piped to and it will write files. In our case we take all the files in app folder, app/*.*, and write them into public folder.

Next task is building the scripts. In our case this is moving the scripts into the public directory. We might have used minification, optimization and concatenation, we don’t need it. We have an extra task that uses requirejs optimizer to optimize the script files and build a stand-alone code you can check out the source code for this article.

gulp.task('build-commonjs', function() {
  var mergeStream = require('merge-stream');

  var bowers = gulp
      .src(['app/bower_components/**/*.js'])
      .pipe($.changed('public/scripts/lib'))
      .pipe(gulp.dest('public/scripts/lib'));

  var common = gulp.src(['app/scripts/**/*.js'])
      .pipe($.changed('public/scripts/app'))
      .pipe(gulp.dest('public/scripts/app'));

  return mergeStream([bowers, common]);
});

Note that, we use merge-stream that combines two gulp streams together, and we return the stream. Remember we passed an extra parameter, cb to gulp that made the task asynchronous, this is a second way of doing that, returning the stream also makes the task run asynchronous. The third way of making a task asynchronous is to return a promise. For more information about gulp API see docs.

Finally we have our build task, that will run the clean, jshint-fail, and build-requirejs tasks synchronously in that order.

gulp.task('build', function(cb) {
  runSequence('clean', 'jshint-fail', 'build-commonjs', cb);
});

gulp.task('default', ['build']);

Note that, we also have a special default task, that will run with only gulp command, opposed to gulp build.

By default, tasks are run concurrently, as opposed to grunt which runs the tasks in series. To run a list of tasks in sync either tasks have to be asynchronous and have to depend on each other or you need to run tasks via runSequence.

gulp; lint, and inject some code!

Next task, is linting our code with jshint, there is a gulp plugin we access it using $.jshint, remember gulp-load-plugins.

gulp.task('jshint-fail', function() {
  return gulp.src(['gulpfile.js',
    'app/**/*.js',
    '!app/bower_components/**'])
        .pipe($.jshint())
        .pipe($.jshint.reporter('jshint-stylish'))
        .pipe($.jshint.reporter('fail'));
  });

Note that we pipe the jshint plugin and the jshint reporters to the gulp stream. Visit here for more information on jshint plugin.

There is an npm module bower-requirejs, that wires up installed bower components into requirejs config, we also use it in our gulp task, though I won’t show it here.

gulp; serve and watch files!

Next task, is serving our project to the browser, we use gulp-webserver plugin for that. It will start a connect server and serve our files as well as watch them and run a live reload server and inject a live reload script so the browser will auto refresh when a file is changed.

Final task is watch task, that will watch our source files for changes and run various tasks on change.

gulp.task('watch', ['serve'], function() {
  gulp.watch('app/scripts/**/*.js', ['build-commonjs']);

  gulp.watch('app/*.*', ['build-extras']);
    
  gulp.watch('bower.json', ['bower-rjs']);

  gulp.watch('gulpfile.js', function() {
    console.log($.util.colors.red('\n----------' +
                                  '\nRestart the Gulp process' +
                                  '\n----------'));
  });
});

You might wonder, gulp-webserver is also watching the folders, why we need gulp to watch again. Well gulp watches the source files, and runs tasks that compiles the source into the public folder, meanwhile gulp-webserver watches the public folder for changes, and refreshes the browser on change.

Also note that ‘watch’ task depends on ‘serve’ task, we tell that by passing a dependency array as the second argument to gulp.task.

Here are the list of dependencies we’ve used in this article and the command to install and save them in the package.json.

$ npm install --save-dev gulp gulp-load-plugins gulp-changed gulp-imagemin gulp-livereload gulp-webserver gulp-util gulp-jshint jshint-stylish rimraf merge-stream run-sequence bower-requirejs requirejs

There are many gulp plug-ins listed in the official website. Yet gulp is sensitive about plugins, that there should be one, if it is only necessary, and they have a blacklist of plugins that should not be used, so pick your plugins carefully, and use bare npm modules wherever possible. Also checkout the documentation and recipes for achieving various tasks.

Conclusion

In this article we have built a project template for Phaser using gulp as our build tool, and requirejs as our module loader. We have learned how to define gulp tasks and how to make use of gulp plug-ins to enable us a nice development environment, with watching files and live-reloading our changes. Note that yet we used Phaser as a sample project, this will give you the main idea, and hopefully you will apply the same principles to your specific projects. You can find the full source code at github.

In the next article we will use this project template to build a yeoman generator, we will also show test driven development using mocha and yeoman test helpers.

In previous post, we’ve seen how to navigate in our site using backbone.js. In this post, we will go back to server side, and build our blog api using baucis. At the end of this tutorial, you will be able to query your mongodb database and pull blog information.

Building Schemas with Mongoose

Firstly, let’s define our blog schema. We will use mongoose to interact with mongodb. Go to app/scripts directory and create a new file named schemas.js.

app/scripts/schemas.js

var mongoose = require('mongoose');
var baucis = require('baucis');

// Define journal schema
var journalSchema = mongoose.Schema({
    paper: {name: String, url: String},
    author: {name: String, photo: String },
    title: String,
    body: String,
    date: { type: Date, default: Date.now},
    meta: {
        votes: Number,
        favs: Number,
        tags: { type: String, lowercase: true, trim: true }
    }
});

// db connection string
var MONGO_URI = process.env.MONGOHQ_URI || 'mongodb://localhost/test';


// connect to mongodb with mongoose
mongoose.connect(MONGO_URI);

// define a journal model with journalSchema
mongoose.model('journal', journalSchema);

// use baucis to create a rest api
var controller = baucis.rest('journal');

We created a blog schema, connected to our database, defined a model based on our schema, and finally used baucis to create the rest api. Now if you run your server, your api will be available at:

*http://localhost/api* endpoint.

Here is a table, describing available functions:

HTTP Verb /journals /journals/:id
GET Get all or a subset of documents Get the addressed document
POST Creates new documents and sends them back. You may post a single document or an array of documents. n/a
PUT n/a Update the addressed document
DELETE Delete all or a subset of documents Delete the addressed object

To test it go to *http://localhost/api/journals* in your browser, it should return an empty array. Because we don’t have any blogs in our database yet.

Using Mongo Shell

Though we can post blogs to our database using the api, we will simply create blogs using the mongo shell. Mongo shell is CLI for using mongodb. run mongo in your console to open the shell. Issue the following commands to create your first blog entry.

# This is for commenting
   # just ignore it.

   # List databases
   show dbs
   
   # Choose database, test
   use test

   # List collections in the database
   show collections

   # journals collection is created when we created a model with mongoose.
   # collection is the plural form of our model.

   #list the contents in journals collection
   # it should be empty
   db.journals.find()

   # place a new blog entry in journals collection
   # here we define only title and body attributes, you can define other attributes as well

   db.journals.create({title: 'My Simple Blog 1', body: 'Simple body for testing' })

   # list the contents again to see the newly created blog
   db.journals.find()

Mongo shell is interpreting javascript code here, so use javascript. Undefined attributes will have their defaults value We can disable null values for attributes, but for simplicity we don’t.

Now go to http://localhost/api/journals again and see the newly created blog entry.

In the next post, we will consume this api with backbone.js and list the blogs in our main page.

In previous post we’ve seen how to setup a node.js server and serve our index.html. In this post, we will implement navigation in our site using backbone.js. At the end of this tutorial, you will be able to navigate between tabs in your site.

Router

Backbone.Router provides methods for routing client-side pages. We will start by creating a custom router class. Place this in js/app.js

var AppRouter = new (Backbone.Router.extend({
    initialize: function() {

    },
    
    routes: {
        
    }
}))();

When creating a router you may pass its routes hash directly, or manually create a route for the router. We will do it manually inside initialize function. But first let’s define our routes in an object.

js/app.js

var NavigationRoutes = {
    "Home": {
        route: "",
        view: Home
    },
    "About": {
        route: "About",
        view: About
    },
    "default": {
        route: "*default",
        view: NotFound,
        hide: true
    }
}

NavigationRoutes object will keep our routes for the application. The keys are title for the route. “route” property is the routing string. “view” property defines the backbone view objects that will be rendered for the route, they are the Route Views We will define them later. Finally “default” key has a “hide” property telling that it will be hidden on navigation tab. We can add different properties as we like here, for example “permissions” property might tell a navigation tab to be only shown for an admin.

Next we will add these routes to our router. Place this function in your Backbone router.

js/app.js

initialize: function() {

        this.route(NavigationRoutes['default'].route, 'default');

        for (var key in NavigationRoutes) {
            if (key != "default")
                this.route(NavigationRoutes[key].route, key);
        }
    },

Here we traverse NavigationRoutes, and add each route in our router. There is a little logic there for the default route. We add the default route first, so it becomes the last route to be looked. The default route is defines as “*default”, this is called a splat and matches everything in the url. So anything else that is not defined previously will be matched by default route, and NotFound view will be rendered.

Navigation View

Bootstrap NavBar

Before we dive into Backbone.View, let’s see our html code for the navigation bar. Place this inside your index.html

index.html

<nav class="navbar navbar-default">
      <div class="navbar-header">
        <button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar-collapse">
          <span class="sr-only"> Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href='#'> Simple Blog </a>
      </div>

      <div class="collapse navbar-collapse" id="navbar-collapse">
           
        <ul class="nav navbar-nav" id="nav-item-container">
        <!-- Navigation tabs will be inside #nav-item-container here -->
        </ul>
      </div>

    </nav>

     <div class="container" id="container">

    </div>

Our Backbone.View for the navigation tabs will control the #nav-item-container. #container element will contain the navigated content.

Navigation Bar View

Backbone views don’t determine anything about HTML, it can be used with any templating library. Underscore.js in this case. Place this in js/views/nav.js

js/views/nav.js

var Navbar = Backbone.View.extend({
    initialize: function(options) {

                // we pass the NavigationRoutes as an option, later we traverse the routes in render function.
        this.routes = options.routes;


        // router will fire route event whenever url changes, we rerender our view
        // on each url change
        Backbone.history.on('route', function(source, path) {
            this.render(path);
        }, this);
    },

    // events hash that handles events in our view
    events: {
                // click handler for a navigation tab
        'click a': function(source) {
            var hrefRslt = source.target.getAttribute('href');
            Backbone.history.navigate(hrefRslt, {trigger: true});

            // Cancel the regular event handing so that we won't actually
            // change URLs We are letting Backbone handle routing
            return false;
        }
    },

    render: function(route) {
            // Clear the view element
        this.$el.empty();

        // this is the underscore template for a navigation tab.
        var template = _.template("<li class='<%=active%>'><a href='<%= url%>'><%=visible%></a></li>");

        // Traverse the NavigationRoutes
        for (var key in this.routes)
        {
                // don't render if route is hidden
            if (!this.routes[key].hide)
                this.$el.append(template({url: this.routes[key].route, visible: key, active: route === key ? 'active': ''}));
        }
    }
});

Backbone.View’s looks complicated at first, render function is used to render the actual view, in our case, its about manipulating the dom. The dom is referenced by this.el, equal to #nav-item-container. this.$el references the jquery dom object, equal to $(‘#nav-item-container’). We don’t set this.el in this code we will pass it as parameter when we initialize our view later.

template variable defines an underscore template. It is our navigation tab. A json model is passed to the template to render actual html. Finally html is appended to this.$el. This is done for each element in NavigationRoutes. We can add any logic we wan’t here to render, for now, we only use hide property for the NavigationRoutes to control if a link should be rendered or not.

Navigated Content View

Next, we define a view for navigated content. It will control the #container element.

js/views/nav.js

var Content = Backbone.View.extend({
    initialize: function(options) {
                // pass the NavigationRoutes as an option
        this.routes = options.routes;

        // Listen for route changes, and render when a route changes.
        Backbone.history.on('route', function(source,path) {
            this.render(path);
        }, this);
    },

    render: function(route) {
        this.$el.html((new this.routes[route].view()).render().el);
    }
});

This is a bit simpler, tricky part is the render function. Here, we initialize the view property defined in our NavigationRoutes, view contains the Backbone.View elements for each route. Call the render method for the View element. render method will return the Backbone.View, (we will define that later) , so we can access the el property. Finally we set this.$el.html to the dom element of the route view.

Phew, that’s quite hard to explain, hope it becomes clear later.

Individual Route Views

Next, we define the route views, these will be rendered into the #container. Place this in your js/views/main.js.

js/views/main.js

var Home = Backbone.View.extend({


    template: _.template($('#home-template').html()),
    
    initialize: function () {
        
    },

    render: function () {
            // Set the html to the template
        this.$el.html(this.template());

        // We return this, so parent view can access the this.el property
        return this;
    }
});


var About = Backbone.View.extend({

    template: _.template($('#about-template').html()),
    
    initialize: function () {
        
    },

    render: function () {
        this.$el.html(this.template());
        return this;
    }
});


var NotFound = Backbone.View.extend({

    template: _.template($('#404-template').html()),
    
    initialize: function () {
        
    },

    render: function () {
        this.$el.html(this.template());
        return this;    }
});

Each view defines an underscore template property. Templates are initialized with some html from jquery dom elements. We will define them later in our index.html. render method simply sets the view’s el property to the underscore template, and returns the view which was used in our navigated content view.

Route View Templates

We define these templates in our index.html.

index.html

<script type='text/template' id='home-template'>
       Home
    </script>

    <script type='text/template' id='about-template'>
      About
    </script>

    <script type='text/template' id='404-template'>
      Oops..
    </script>

Since these templates should not be readily visible in the page, we wrap them in script tags and give each an id. We referenced these templates with jquery before.

While we’re at it, let’s add the new script files we’ve created to the index.html as well.

index.html

<script src="/js/views/nav.js"></script>
      <script src="/js/views/main.js"></script>
      <script src="/js/app.js"></script>

Main Function

js/app.js

$(document).ready(function () {

    new Navbar({el: $('#nav-item-container'), routes: NavigationRoutes});
    new Content({el:$('#container'), routes: NavigationRoutes});


    Backbone.history.start({pushState: true});
});

Finally the main function, initializes Navbar and Content views. And calls Backbone.history.start We pass the el property for the views here as mentioned previously. and NavigationRoutes is passed as an option.

By default backbone routes the url’s with a containing # symbol. Backbone.history.start is passed pushState:true parameter, to get rid of the #.

Congratz, now you have a working implementation of a navigated content using backbone.js

Final Touch

As a final touch, let’s put some html inside our #home-template so it looks more like a blog.

index.html

<script type='text/template' id='home-template'>

      <div class="row">
        <div class="col-lg-12">
          <h1 class="page-header"> Blog Home <small> Blog Homepage</small></h1>
          <ol class="breadcrumb">
            <li><a href="/">Home</a></li>
            <li class="active">Blog Home </li>
          </ol>
        </div>
        
      </div>

      <div class="row">
        <div class="col-lg-8" id="blog-list-view">

          
          <ul class="pager">
            <li class="previous"><a href="#">&larr; Older</a></li>
            <li class="next"><a href="#">Newer &rarr;</a></li>
          </ul>
          
          <div id="blog-list-container"></div>
          
          <ul class="pager">
            <li class="previous"><a href="#">&larr; Older</a></li>
            <li class="next"><a href="#">Newer &rarr;</a></li>
          </ul>
        </div>

        <div class="col-lg-4">
          <div class="well">
            <h4> Blog Search </h4>
            <div class="input-group">
              <input type="text" class="form-control">
              <span class="input-group-btn">
                <button class="btn btn-default" type="button">&nbsp;<i class="fa fa-search"></i> </button>
              </span>
            </div>
          </div>

          <div class="well">
            <h4>Popular Blog Categories</h4>
            <div class="row">
              <div class="col-lg-6">
                <ul class="list-unstyled">
                  <li><a href="somestuff">some stuff</a></li>
                  <li><a href="somestuff">some stuff</a></li>
                  <li><a href="somestuff">some stuff</a></li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>
      
      
    </script>

Getting Started Full Stack - Building a simple blog - Part 1

In this post, we will install the required components to build a simple blog. In the end of this post, you will be serving a hello world page, with a responsive bootstrap theme, and all necessary script files.

Server Side:

Node.js
Host the website, on javascript platform, based on Google’s V8 JavaScript Engine
Express
Web application framework for node.js
Mongodb
Open-Source NoSQL database written in C++. Also look at Mongoosejs, simple mongodb driver for nodejs.
Bower
Package manager for the web. Simplifies installing client side resources.

Client Side:

Bootstrap
Responsive front-end css framework.
JQuery
Javascript, for interactive webpages.
Backbone.js
Gives structure to web applications. Models, Collections and Views.

Let’s get Started

Introduction

Building a simple blog, solving problems along the path, it’s gonna be fun.

Web Server

Nodejs hosts the website. Serving pages, scripts and stylesheets. Expressjs is a web application framework, simplifies dealing with serving pages. It uses middleware to extend functionality like plugins.

Database

Mongodb our nosql database. it has no relational tables, but nested documents. Mongoosejs is our driver for mongodb on nodejs. Model schemas and operate.

Content Management

Bower downloads scripts and stylesheets from web into our path, we will simply reference it.

CSS Theme

Bootstrap gives the site a nice look. Responsive, meaning it will behave when resized, looks nice on any device.

Javascript

JQuery, main dependency for manipulating dom. Backbone.js is mvc framework for building client side interaction.

Backbone.js is lightweight, and heavily depends on Jquery, a popular alternative is angularjs. Angular.js doesn’t need Jquery, and is a higher level framework.

Backbone.js doesn’t implement templating. Templating is supported by mainly underscore.js or other libraries. (handlebarsjs, mustache)

Backbone.js will teach us more about structure, templating, jquery, and javascript. We should move to higher level frameworks later on. (possibly built on backbonejs) Finally, backbonejs isn’t bound to SPA’s, we may use it for other projects later on (more coming after this).

Installation

I use ubuntu/linux you should find a way to install on your platform, read the guides and google.

Npm, Node.js

# install node.js
sudo add-apt-repository -y ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs

# test should look like: v0.10.12
node -v

Or, follow the Instructions

This will also install npm package manager. Npm is used to install packages required by node.js.

Mongodb

# install mongodb
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
sudo apt-get update
sudo apt-get install mongodb-10gen

# test should bring mongo shell, Ctrl-c to break
mongo

More Instructions

Bower

#install bower
npm install -g bower
# test should look like: 1.2.8
bower -v

More Instructions

Congratz, this is enough to host our simple blog. We will learn these tools along the way. Now let’s build our codebase.

Directory Structure

Build the following directory structure. public folder will host our public pages, scripts and stylesheets. ‘scripts’ folder will host javascript code for running the nodejs server, interacting with mongodb.

../mysimpleblog
`-- app
    |-- public
    |   `-- js
    |       |-- collections
    |       |-- models
    |       |-- routers
    |       `-- views
    `-- scripts

Configuration

Package.json

package.json is a packaging format for node.js. Important part here is dependencies, where we declare dependencies for our project. Place it in root folder of your project, where your app folder resides.

express : web application framework, It uses middleware to handle http requests. Middleware could be third party code, which we will use shortly.

baucis : Baucis is Express middleware that creates configurable REST APIs using Mongoose schemata

connect : Lower level middleware for node.js, not important for us any time soon. baucis needs it so we include.

.bowerrc

.bowerrc file will change bower’s default components folder. Place it in root folder of your project.

Installing packages

Server side dependencies are defined in package.json, and installed with npm. Client side dependencies are defined in bower.json and installed with bower.

However we won’t be using bower.json rather install the required files manually.

# install server side packages (defined in package.json)
npm install
#install client side packages manually with bower
bower install bootstrap
bower install fontawesome

bower install jquery
bower install backbonejs
bower install underscore

Server side packages can be directly used in javascript code, we will see how that’s done later. Client side packages are simply files downloaded in directory we defined in .bowerrc so you can check it out there. We will reference them in our index.html.

Setting up the server

Final step is to actually setup the server, so we can host our files. Go to app/scripts directory and create the two files below.

Further information: middleware , require .

Finally we need an index.html to serve, and we are ready to launch. Go to app/public directory and create the file below.

Launch Time

To run the server go to app folder and run:

# test: output should be 
   # - listening on port 3000
   node ./scripts/web

Now launch your browser and locate to http://localhost:3000.

One final note here is that, if you make changes inside app/public folder, a browser refresh is enough to see the changes, if you make changes inside app/scripts folder, you need to restart the server, in order to changes to take effect. There are tools to live reload every change but that’s for a later time.

Please share your thoughts below. Thank you.