MEAN stack – A Hands on Tutorial

Tweet about this on TwitterShare on LinkedIn0Share on Google+0Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page

MEAN stack – A Hands on Tutorial

Also checkout a lighter version of the Todo App using DiskDB instead of MongoDB : Building a Todo App with DiskDB

If you are new to MEAN, I would recommend checking out my MEAN Workshop.

Looking for a way to set up Vagrant to work with M.E.A.N. Stack applications? Take a look at M.E.A.N. Stack Development with Vagrant

If you have been working in the  Nodejs/Web development world, you must have heard about MEAN. If you did not, MEAN stands for

  • M – MongoDB
  • E – Expressjs
  • A – Angularjs
  • N – Nodejs

Sweet right! This IMO is the next gen technology stack to build scalable and efficient web applications that uses Javascript on both the server and the client.

In this post, we will be building a simple Todo App. We will be building the app from scratch, which will give you an idea as what component goes where and how to configure it. If you already have taken a stab at MEAN stack generators/frameworks, you must have noticed the complex file structures, and you are not sure which files gets wired to which other file.  We will be demystifying them but in simple a Todo app.

The final product we are going to build will look like

Screen Shot 2014-08-22 at 7.53.26 amScreen Shot 2014-08-22 at 7.53.45 amScreen Shot 2014-08-23 at 8.29.18 pm

You can find a demo here. You can find the complete code here.

So, let us get started.

Architecture

We will be building a Todo application, where a user can add a new todo, edit , mark it as completed and delete it. For this, we will be using MongoDB as our data persistence layer. We are going to have one collection named Todo, that will store all our Todos.

For our server side layer, we will be using Nodejs. We will be using a few Node packages to manage and maintain our application. Expressjs will be acting as our server. Expressjs is responsible for interacting with MongoDB (fetching and saving data). And finally our client side Javascript framework would be Angularjs. Angularjs is responsible for managing the different states of UI and also interacting with the Expressjs server & syncing the data.

Prerequisites

I would highly recommend the following posts before you continue development.

Nodejs

Expressjs

Angularjs

MongoDB

Integration

Getting Started

Now, we have a basic idea as what app we are going to build and with what technologies. So, let us get started. Create a new folder named meanTodoApp. Open terminal/prompt here and run

npm init

to start a new node project and fill it as

Screen Shot 2014-08-23 at 6.12.41 pm

To keep our code organized, we will create two folders inside the meanTodoApp folder. One server and the another client. This step is totally optional and you can organize and arrange your code as you wish. For this post, I will be creating the two folders.

First, we will setup the server layer. We will install Expressjs module and its dependencies. Back to terminal/prompt and run

npm i --save express morgan body-parser cookie-parser debug ejs

This will take a couple of minutes for NPM to download and save all the packages. CD into the server folder and create a new file named app.js. This fill will hold the Expressjs config and the code to start the server.

Open app.js in you favorite editor and fill it up like

Next, as referred in the code above, we will create 2 new folders inside the server folder. One for routes and another one for views.

Before we continue further, we will download the node module to interact with MongoDB.

npm i --save mongojs

Now, create a new file named index.js inside the routes folder. This file will hold the traditional REST methods the GET, POST, PUT and DELETE for our collection. And inside these methods, we write the logic to handle the same. Update index.js as below

We are using Mongojs to interact with MongoDB from the Expressjs layer. This here is the integration point between MongoDB and Nodejs/Expressjs. And this is also the integration point between the client Angularjs and Nodejs/Expressjs. Simple right?

PS : If you like, you can create a new folder and dump the logic for each method inside a new file like get.js, post.js, put.js and delete.js. And then include them in above as applicable. 

To test the application we have built so far, in terminal/prompt from inside the server folder run

node app.js

This will start the express server on port 3000. Make sure MongoDB is running (if not you can start it by executing mongod  in a new terminal). Then navigate to  http://localhost:3000/api/todos this will hit the get()  in routes/index.js, which will query MongoDB for all the records inside the todos collection and return them. This will be an empty array, since we have not added any data yet.

Instead of manually running the project every time, we will be using gulp a node based taskrunner to manage our project. First, we will set up gulp globally. Run

Windows Mac/*nix
npm i -g gulp    sudo npm i -g gulp

Then we will install the required plugin. Execute

npm i --save-dev gulp gulp-nodemon gulp-watch gulp-jshint gulp-livereload

This will take a couple of minutes. Now at the root of the project, create a new file named gulpFile.js and add the below code.

Save all the files and execute

gulp

And you should see something like

Screen Shot 2014-08-23 at 7.02.49 pmNow you can navigate to http://localhost:3000/api/todos  and you will see the same output. Since we have added live reload and watch, we can make changes to the files and they will automatically be refreshed for you in the browser.

You can keep the gulp task running and continue development.

We have almost completed the server side development. Now all we need to do is dispatch a page when the user tries to access the base URL.

Now, inside the views folder create a new file named index.html. For now, update it with the below one line

Save all the files and back to the browser. This time, we will access the base URL http://localhost:3000  and you should see

Screen Shot 2014-08-23 at 7.09.02 pmSimple right!

The project we have developed so far should look like

Screen Shot 2014-08-23 at 7.12.12 pm

Continue development

Now, we will focus on the client side. We will be building the Angularjs piece, that is responsible for interacting with the Expressjs REST API endpoints and updating the user interface accordingly.

To handle our client side dependency, we will use Bower. Before start using Bower, we need to install it globally. Run

Windows Mac/*nix
npm i -g bower    sudo npm i -g bower

Once this is done,  add a new file named bower.json at the root of the project. Open it inside your favorite editor and update it like 

Now, add a new file at the same level as bower.json and name it .bowerrc. This file will hold the bower configs. For now, we will setup the directory. Open .bowerrc in you favorite editor and update it as

And then back to terminal. CD back to the project root folder and we will run bower install command to download Bootstrap (for UI), Angularjs and jQuery. Run

bower i --save jquery bootstrap angular angular-route

This will download the libs to client/lib folder. Next, create 3 new folders inside the client folder named css, js and partials. 

Now, open server/views/index.html and update it as

Back to browser and you should see the update UI. Now, we will create a new angular module named todoApp. Create a new file named app.js inside client/js folder and update it as below

Add the reference to this file inside server/views/index.html below the angular reference

<script type="text/javascript" src="/js/app.js"></script> 

Next, we will add a Angular factory, which is responsible for interacting with the Expressjs REST endpoints. Inside the client/js folder create a new file named factory.js. Update it as below

Simple right!

Now, we will add the controller. Create a new file named controllers.js inside client/js folder. Update it as below

Now, we will create the todo.html partial. Inside the client/partials folder, create a new file named todo.html and update it as below

And finally on the client side, we will add a few custom styles to the app. Create a new file named style.css inside the css folder and updated it as below

Finally, we will add a reference to factory.js, controller.js and styles.css inside server/views/index.html. The updated file would be

That is it, you have successfully developed a MEAN app!!

Save all the files and navigate to  http://localhost:3000/ (assuming gulp task is running). And you should see

Screen Shot 2014-08-23 at 7.58.08 pm

Add a new Todo,

Screen Shot 2014-08-23 at 7.59.06 pm

You can play around with the app and test it out. You can also log into the Mongo shell and verify the data

Screen Shot 2014-08-23 at 8.02.07 pm

Simple and easy right! Now you know where which component goes when you are developing an end to end application using MEAN. You can expand on this application, add more features integrate authentication etc.


Thanks for reading! Do comment.
@arvindr21

Tweet about this on TwitterShare on LinkedIn0Share on Google+0Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page
  • Pintoo gautam

    First complete tutorial. That really helps me to complete my first demo app. thank you so much.

  • Devendra

    Great tutorial

  • Hao

    gulp-watch caught me as well. Seems the API changed since. But I don’t know if I really fixed it or not. But the error is gone after I changed gulp config to this:

    .pipe(watch(_paths, [{
    emit: ‘all’
    }]))

  • abc

    very nice

  • naveen m2999

    hi arvind could you help me out i have stuck at gulpfile i am getting an error see the image attached

    my gulpfile
    (function() {
    ‘use strict';
    var gulp = require(‘gulp’),
    nodemon = require(‘gulp-nodemon’),
    watch = require(‘gulp-watch’),
    jshint = require(‘gulp-jshint’),
    livereload = require(‘gulp-livereload’),
    _paths = [‘server/**/*.js’, ‘client/js/*.js’];

    //register nodemon task
    gulp.task(‘nodemon’, function() {
    nodemon({
    script: ‘server/app.js’,
    env: {
    ‘NODE_ENV': ‘development’
    }
    })
    .on(‘restart’);
    });

    // Rerun the task when a file changes
    gulp.task(‘watch’, function() {
    livereload.listen();
    gulp.src(_paths, {
    read: false
    })
    .pipe(watch({
    emit: ‘all’
    }))
    .pipe(jshint())
    .pipe(jshint.reporter(‘default’));
    watch(_paths, livereload.changed);
    });

    //lint js files
    gulp.task(‘lint’, function() {
    gulp.src(_paths)
    .pipe(jshint())
    .pipe(jshint.reporter(‘default’));
    });

    // The default task (called when you run gulp from cli)
    gulp.task(‘default’, [‘lint’, ‘nodemon’, ‘watch’]);
    }());

  • Prashant Deshpande

    Thanks a lot… Very good tutorial on MEAN app…. I have completely understood how to setup environment for MEAN:):). But I have one question, here you have manually included scripts/stylesheets in index.html, can we use any tool to add it automatically? is there any ref for this?

  • Abhijeet Ramgir

    Hey, the link to the video tutorial doesn’t load,,?

  • Johannes Kurz

    Hey there. As a decade long PHP Programmer your tutorial was a one day kickstart into mean stack dev. I got all up and running already with my own project.

    A question still remains: bower does not compile the dependencies so there is no dist folder in bootstrap nor in jquery. bootstrap was compileable with
    npm install && npm install grunt && grunt dist

    but how can I compile jquery?
    Is there any possibility to let bower do the job anyway?

    greetings

  • Bouteraa

    can i apdate the current versions into the virtual machine ? if yes , without any issues
    ?

  • Saurav Jain

    Anyone give me demo how to create hybrid mobkile app using meanstack. Currently my app is built in webapp using meanstack framework

    • / Arvind Ravulavaru

      Replace your Web UI with any Cordova powered framework like Ionic and you should be good to go. You can check out Ionic posts in this blog for more information on that.

      • Saurav Jain

        Hi Arvind,

        Any Demo APP that is built using meanstack in hybrid mobile app in ionic framework as you told me use ionic framework?

        Can you give me reference link for creating the hybrid mobile app using meanstack. Currently my current app is in webapp using meanstack framework?

        • / Arvind Ravulavaru
          • Saurav Jain

            Hi Arvind,

            Thanks for Info.This is really a great tutorial.

            I have some doubts.Can you please clear the doubts.

            My Current Web APP not hybrid APP that i have built using MEAN stack (Server side + Client Side coding done both here).

            So Now Also I want to create hybrid APP(Android + IOS APP) that is currently built web APP only.

            So Should i need to create client side code for hybrid APP in new project and use rest APP call for fetch data from server and that API call need to create in my web APP meanstack application where my server side reside using menstack?

            Also in hybrid app using ionic framework, is there no use of meanstack framework?

            For Hybrid APP, we need to just create html file for view and controller and service for it thsts it?

            Can you please clarifyfy my points? I am very thankful to you

          • / Arvind Ravulavaru

            Saurav, I recommend you spend more time to understand what MEAN stack is. If you know what MEAN stack is, you would not have the above questions.

            To answer your question. In the MEAN stack, the Expressjs REST APIs are consumed by the Angularjs app bridging the client & server connectivity. In a Hybrid eco-system, the Angularjs piece will be replaced with a Cordova powered Framework like Ionic. In fact if you are using Ionic as your mobile Hybrid framework, you can reuse most of your Angularjs services.

  • Sandesh Marathe

    when i enter any input and hit enter nothing happen… please help

  • rizwana

    i get todoApp not defined error in app.js,controller.js and factory.js…. may i know the reason why?

  • Raju N

    Awesome tutorial on MEAN stack, loved the article mate, good job and please keep posting more of these, coz we are hungry..

  • node coder

    hi Arvind!
    this is awersom plugin
    but i have one issue when i save data in diskdb but when i read that file then it’s give a blank result.
    any solution for this one.

    • / Arvind Ravulavaru

      Can you share the code as how you can implemented Diskdb? Also can you comment here : /building-todo-app-diskdb/ about disk db? This example is based on MongoDB.

  • mean dev

    diskdb is not load the collection after save data

  • PrabhakarPandey

    Hi Arvind thanks for the tutorial. I have a question when any user gives the url directly it is showing the JSON data. As in your app also it is happening.
    If I put : http://mean-todo-app.herokuapp.com/api/todos
    directly it will show all the data in json form.
    Is there any way to fix this?

    • / Arvind Ravulavaru

      Thanks PrabhakarPandey. This is not a bug! This is the REST end point which provides the data. If you want to make your MEAN app more secure that no one can see the data except you, checkout : Architecting a Secure RESTful Node.js app

      Thanks.

  • Adnan

    sir, i am very new on mean. My app did not able to connect with data with database after adding a todo, My app did not show and todo. i follow all steps exactly and receive exactly except when i run gulp. there is a error in watch plugin.

    • / Arvind Ravulavaru

      Hello Adnan. Can you tell me what error you are facing?

  • jrutter

    Fantastic write up, definitely one of the better MEAN stack tutorials I have gone thru.

    • / Arvind Ravulavaru

      Thanks jrutter!

  • Sagar Sutaria

    Best tutorial I’ve ever come across. Thanks much.

    • / Arvind Ravulavaru

      Thanks!

  • Shikhar Chauhan

    Awesome write up.. I have been looking for such a clean written basic tutorial to understand MEAN stack, for quite some time. I request you to write some on good practices and token based authentication.
    Thanks again for the article :) … keep writing…

  • http://www.brycearcher.com/ Bryce Archer

    Awesome tutorial! Is there a reason why you are declaring your angular module as in client/js/app.js without the var keyword? Doesn’t this pollute the global namespace?

    • / Arvind Ravulavaru

      Thanks Bryce! No specific reason. Old habit of mine to keep the main module in the global space.

      • http://www.brycearcher.com/ Bryce Archer

        Good to know. Really enjoyed building this :-)

  • Mana

    Thanks a lot for this, that helped me a lot to quickly get started with the MEAN stack – that saved me a lot of googling around…

    I wish you used browserify to bundle up the dependencies but I understand there isn’t much to bundle anyway 😛

    • / Arvind Ravulavaru

      Thanks Mana.

  • SundaraPandyan SA

    Arvind, a question off topic, when i tried to deploy the todoapp over heroku I am facing an error related to the proc file usage. Can you please share the Procfile as well in Github.. or share some insight on its usage wrt heroku…

  • SundaraPandyan SA

    Arvind, is there a reason why you chose Gulp against Yeoman and Grunt for scaffolding?

  • Lawson Feltman

    @arvindravulavaru:disqus thanks a ton! This is a really great walkthrough. I just wanted to let you know that I am struggling to solve the exact same gulp error as @karthik_naidu:disqus… Please let me know if you find a solution. I can’t figure out what may be wrong with the array of strings. My _paths var is indeed set to an array of strings, so I don’t understand why gulp-watch is seeing an object instead of an array of strings…

  • Bruce

    Wonderful Tutorial. I was searching whole web for almost two days for MEAN stack tutorial and I finally found something simple and easy to implement. Thanks a lot @arvindravulavaru:disqus.
    Got to know about new technologies gulp and bower.
    I have few question but I will do some research and then know about them.
    Keep sharing your knowledge .. :)

    • / Arvind Ravulavaru

      Thanks Bruce. Glad I could be of help. Feel free to shoot any questions. Thanks.

      • Bruce

        The application is working like a charm on my machine. But while going through the code I had few questions,

        – How does mongdb get connected? We are using “mongojs” but how is the connection made? Where is the connection string specified?

        – How to debug on server side? I need to check the parameter values on server side code? How to use logger to check these values? On client side I have used console.log statements.

        • / Arvind Ravulavaru

          Hello Bruce. To answer your questions

          1. We make the connection in route.js here : https://github.com/arvindr21/MEAN-Todo-App/blob/master/server/routes/index.js#L6

          If you go through the readme of mongojs, you will find

          We are using the simple usage, since our DB is in our local machine and runs with default settings.

          2. You can debug server code using any of the following ways

          a. console.log(obj);
          b. util.inspect(obj);
          c. debug from command line as in node debug index.js ( http://nodejs.org/api/debugger.html )
          d. node-inspector and node-debug index.js

          Few more resources

          * https://www.youtube.com/watch?v=JNSy1roM82k
          * https://www.youtube.com/watch?v=03qGA-GJXjI

          Thanks.

          • Bruce

            node-inspector awesome debugger. Thanks @Arvind.

          • / Arvind Ravulavaru

            Thanks!

  • Karthik Naidu

    OMG..! I built my first MEAN stack app, Thank you so much Arvind….!

    Also, can you help me to fix this issue, Gulp watch is not working in my machine, and it throws below error –
    [02:27:30] ‘watch’ errored after 5.63 ms
    [02:35:51] Error in plugin ‘gulp-watch’
    Message:
    glob should be String or Array, not object

    – I tried to reinstall gulp-watch couple of times, but still same issue.
    Thanks In Advance

    • / Arvind Ravulavaru

      Thanks @karthik. The error may be because of the _path variable in gulpfile.js. This variable should be an array of strings. Like we declared above.

      Thanks.

      • Karthik Naidu

        Here is the variable –
        _paths = [‘server/**/*.js’, ‘client/js/*.js’];

        • Lawson Feltman

          I am trying to sort out this same issue, i have the same variable in _paths… did you guys resolve this issue? Thanks Arvind for an AWESOME tutorial

          • / Arvind Ravulavaru

            Thanks Lawson Feltman!

            Can you share your gulpfile.js? I can take a quick peek.

            Thanks.

          • Lawson Feltman

            Hi Arvind,

            Here is my gulp file. I am getting the exact same error as Karthik.

            ___

            (function() {

            ‘use strict';

            var gulp = require(‘gulp’),

            nodemon = require(‘gulp-nodemon’),

            watch = require(‘gulp-watch’),

            jshint = require(‘gulp-jshint’),

            livereload = require(‘gulp-livereload’),

            _paths = [‘server/**/*.js’, ‘client/js/*.js’];

            //register nodemon task

            gulp.task(‘nodemon’, function() {

            nodemon({

            script: ‘server/app.js’,

            env: {

            ‘NODE_ENV': ‘development’

            }

            })

            .on(‘restart’);

            });

            // Rerun the task when a file changes

            gulp.task(‘watch’, function() {

            livereload.listen();

            gulp.src(_paths, {

            read: false

            })

            .pipe(watch({

            emit: ‘all’

            }))

            .pipe(jshint())

            .pipe(jshint.reporter(‘default’));

            gulp.watch(_paths).on(‘change’, livereload.changed);

            });

            //lint js files

            gulp.task(‘lint’, function() {

            gulp.src(_paths)

            .pipe(jshint())

            .pipe(jshint.reporter(‘default’));

            });

            // The default task (called when you run gulp from cli)

            gulp.task(‘default’, [‘lint’, ‘nodemon’, ‘watch’]);

            }());

          • / Arvind Ravulavaru

            Looks like the API changed. Take a look at https://github.com/floatdrop/gulp-watch/issues/90

            replace the existing watch code with below and check

            Thanks!

          • Lawson Feltman

            hey Arvind, thank you so much for your assistance, but this isn’t working for me unfortunately. Granted, the app is working fine, but i would like to have a bug free gulp file… I will keep researching and seeing if I can figure this issue out. Please let me know if you have any further thoughts.

          • / Arvind Ravulavaru

            Oh! Ok, not sure. Option B is to remove gulp watch. Try Browsersync. This is an awesome plugin that will make sure all your browsers are in sync with your code : http://www.browsersync.io

            Gulp plugin : http://www.browsersync.io/docs/gulp

            If you are having issues setting it up, let me know.

            Thanks.

          • / Arvind Ravulavaru

            @Lawson Feltman:disqus FYI : Here is a Gulp file that has auto reload implemented with Browser Sync : https://github.com/arvindr21/MEAN-Todo-App/blob/master/gulpfile.browswersync.js

            Let me know if you face any issues.

          • Kai

            Thanks! This edit worked for me. Maybe it should be mentioned in the code above.

          • / Arvind Ravulavaru

            Fixed. Thanks!

      • Hornigold Arthur

        Arvind, is there a diagram of how the information and requests flow from Client side to Server and back for a say, ADD transaction. Thanks in advance.

  • Ewan

    Thanks so much, Arvind. Its one of the best MEAN stack tutorials available. So clean & concise. Really appreciate it.

    • / Arvind Ravulavaru

      Thanks Ewan!

  • Jeff

    Hey,

    Great tutorial, I just got one quick question, when you wrote “data.data” and “data.data.updatedExisting” in the controllers, the “data” and the “updatedExisting” property exists on the returned object because of how the mongojs module formats records in mongo right?

    Thanks and keep up the great work!

    • / Arvind Ravulavaru

      Hello Jeff, Thanks!

      Yes, when the response comes from the server, it would look like

      And this response is wrapped by angular inside the data object like