Understanding MEANJS Structure

This is the second blog in a series of Hotel Management with MEANJS.
In this blog, we will take an overview at the structure of MEANJS application and try to create a hotel module with some custom fields.

The source code for this blog is at: https://github.com/quanhua92/MEANJS-HotelManagement/releases/tag/v0.2

Table of contents:

1. Introduction to MEANJS
2. Understanding MEANJS Structure

Overview of MEANJS root directory

  • app: contains server-side source code. 
  • config: contains configuration files
  • node_modules: contains server-side modules specified by package.json
  • public: contains client-side source code, including CSS and Javascript library specified by bower.json.
  • package.json: provide meta information of the project and dependence modules in node server-side
  • bower.json: similar to package.json, provides meta information of the project and client-side dependencies

App (server-side) directory:

Structure of app directory
The "app" directory stores all the MVC server files.

  • controllers: stores the Express controllers,  this is where you write your backend logic code.
  • models: stores the Mongoose models, this is where you define your MongoDB backend models. This folder is autoloaded, so you don't have to include your newly created files as in a typical nodejs app.
  • routes: contains the server routing configuration files. This folder is autoloaded in the same way as the models folder. 
  • views: contains the template to render the main pages like index and error pages.
  • tests: stores all your Mocha test files.

A typical workflow in the server-side MVC application is showed in the following picture.

A typical MVC server side work flow

As in the above workflow, when the users go to the home URL, the router will look at the "core.server.routes.js" file and see the routing as follows:
    var core = require('../../app/controllers/core.server.controller');
This means that the router will call the index function is core.server.controller.
The index function is implemented as:
exports.index = function(req, res) {
    res.render('index', {
        user: req.user || null,
        request: req

This means that the controller will pass the request and a user object (if the users signed in) to the view named "index".
This "index" view is specified in "index.server.view.html" file. Then, the "index" template is filled with the data and send back to the user.

Public (client-side) directory:

Structure of app directory

The "public" directory contains all the client-side files.

  • application.js: takes care of bootstrapping the application and attaching the right modules. At this moment, we don't need to modify this file.
  • config.js: contains AngularJS configuration module. We don't need to modify this file. If you want to add an AngularJS module, it is recommended to use the function registerModule in each module.
  • lib: contains the client libraries specified by bower.json.
  • modules: this is the most important folder. This contains all AngularJS modules. This folder is loaded automatically so you can just create a module and use it right away.

Other directories:

Besides app and public directory, there are a few folders and files. However, in order to maintain simplification of this blog, I think that you can check them later.
In the next section, we will try to create a Hotel model and its corresponding server and client code.

Create a Hotel module

In this section, we will create a CRUD module, Hotel. You may want to create files for each folder in the previous section. However, it's recommended to use Yo Generator to make our life easier.
First, change directory to the project folder. And use the command "yo meanjs:crud-module hotels" to create hotels module as in the following picture. If you want to add a "Hotels" to the menu bar, remember to answer Yes to the "menu identifier" question.

Create a CRUD module with yo meanjs:crud-module command

Yo Generator will create the necessary files for us as in these pictures:

New files in app folder
A new folder "hotels" in modules folder
If you try to run the application again with the "grunt" command, you will see that there is a Hotels in the menu bar and you can create a basic Hotel with a Name.

Add some fields to Hotel model

Let's look at the Schema of the hotel in database.
 * Hotel Schema
var HotelSchema = new Schema({
    name: {
        type: String,
        default: '',
        required: 'Please fill Hotel name',
        trim: true
    created: {
        type: Date,
        default: Date.now
    user: {
        type: Schema.ObjectId,
        ref: 'User'
Currently, a Hotel contains a String name, created Date and the creator. Now, we want to add some String fields including address, description, phone number and email address. I will show the steps to add an address field. I hope you can do the same for the other fields.
First,  edit the "app/controllers/models/hotel.server.model.js" and add the following code after the name field:
    address: {
        type: String,
        default: '',
        required: 'Please fill Hotel address',
        trim: true
Then, edit the "public/modules/hotels/controllers/hotels.client.controller.js" to add this field to the AngularJS view.
- Edit the var hotel:
// Create new Hotel object
            var hotel = new Hotels ({
                name: this.name,
                address: this.address
- Add this line at the end of hotel.$save function to clear the form
                $scope.address = '';
After that, we need to edit all the HTML in "public/modules/hotels/views" to add the input for the address in every form.
- create-hotel.client.view.html: duplicate the div.form-group of name and change every "name" to "address"

- edit-hotel.client.view.html: same as in create-hotel.client.view.html

- list-hotels.client.view.html: add a p tag after the h4 tag of hotel.name to view hotel.address
            <p class="list-group-item-heading" data-ng-bind="hotel.address"></p>

- view-hotel.client.view.html: add a p tag after the h1 tag for hotel.name to view hotel.address
        <p data-ng-bind="hotel.address"></p>

Let's restart the application and check if our code works.
We now have a new input for the address.

After a new hotel is created, the address is also showed in the list view.

Now, I hope that you can follow the above steps and add these other fields including hotel description, phone number, email address. If you got trouble, I suggest that you take a look at my GitHub commit (https://github.com/quanhua92/MEANJS-HotelManagement/commit/e00f439050bb518be230cc5a609f04a7d4b5b041).

Share this:


Hello, My name is Quan. I love blogging to share my knowledge to the world. Tell me want you want to read. I will try to blog about it. Have a nice day!


  1. Could you add a comments module to the articles?

  2. Hello. Help me please, why I have totally different folder structure?