Tutorial

Setting Up a MEAN Stack Single Page Application

Draft updated on Invalid Date
Default avatar

By Chris on Code

Setting Up a MEAN Stack Single Page Application

This tutorial is out of date and no longer maintained.

Introduction

Beginning an application from scratch can sometimes be the hardest thing to do. Staring at an empty folder and a file with no code in it yet can be a very daunting thing.

In today’s tutorial, we will be looking at the starting setup for a Node.js, AngularJS, MongoDB, and Express application (otherwise known as MEAN). I put those in the wrong order, I know.

This will be a starting point for those that want to learn how to begin a MEAN stack application. Projects like mean.io and meanjs.org are more fully-fledged MEAN applications with many great features you’d want for a production project.

You will be able to start from absolute scratch and create a basic application structure that will allow you to build any sort of application you want.

Note: (7/8/14): Updated article for Express 4 support. Thanks to Caio Mariano for the help.

Note (10/12/14): Updated article to add Nerd model and make everything clearer.

This article has been updated to work with Express 4.0

What We’ll Be Building

A lot of the applications we’ve dealt with so far had a specific function, like our Node and Angular To-Do Single Page Application. We are going to step away from that and just a good old getting started application.

This will be very barebones but hopefully, it will help you set up your applications. Let’s just call it a starter kit.

Application Requirements

  • Single Page Application
  • Node.js backend with Express and MongoDB
  • AngularJS frontend
  • Modular Angular components (controllers, services)
  • Good application structure so our app can grow

This tutorial will be more based on application structure and creating a solid foundation for single-page MEAN stack applications. For more information on CRUD, authentication, or other topics in MEAN apps we’ll make sure to write other tutorials to fill those gaps.

The Backend Node, MongoDB, Express

Three letters out of the MEAN stack will be handled on the backend, our server. We will create our server, configure our application, and handle application routing.

Tools Required

We will need Node and to make our lives easier, we’ll use bower to pull in all our dependencies.

Bower isn’t really necessary. You could pull in all the files we need yourself (bootstrap, angular, angular-route), but bower just gets them all for you! For more info, read our guide on bower to get a better understanding.

Application Structure

By the end of this tutorial, we will have a basic application structure that will help us develop our Node backend along with our Angular frontend. Here’s what it will look like.

        - app
            ----- models/
            ---------- nerd.js <!-- the nerd model to handle CRUD -->
        ----- routes.js
        - config
            ----- db.js
        - node_modules <!-- created by npm install -->
        - public <!-- all frontend and angular stuff -->
        ----- css
        ----- js
        ---------- controllers <!-- angular controllers -->
        ---------- services <!-- angular services -->
        ---------- app.js <!-- angular application -->
        ---------- appRoutes.js <!-- angular routes -->
        ----- img
        ----- libs <!-- created by bower install -->
        ----- views
        ---------- home.html
        ---------- nerd.html
        ---------- geek.html
        ----- index.html
        - .bowerrc <!-- tells bower where to put files (public/libs) -->
        - bower.json <!-- tells bower which files we need -->
        - package.json <!-- tells npm which packages we need -->
        - server.js <!-- set up our node application -->

We’ll be filling in our files into a folder structure. All backend work is done in server.js, app, and config while all the frontend is handled in the public folder.

Starting Our Node Application package.json

All Node applications will start with a package.json file so let’s begin with that.

        {
          "name": "starter-node-angular",
          "main": "server.js",
          "dependencies": {
            "express" : "~4.5.1",
            "mongoose" : "~3.8.0",
            "body-parser" : "~1.4.2",
            "method-override" : "~2.0.2"
          }
        }

That’s it! Now our application will know that we want to use Express and Mongoose.

Note: Since Express 4.0, body-parser and method-override are their own modules, which is why we have to include them here. For more information, here’s our guide to Express 4.

Express is a Node.js web application framework that will help us create our application. Mongoose is a MongoDB ORM that will help us communicate with our MongoDB database.

Install Node Modules

To install the dependencies we just setup, just go into your console and type:

npm install You’ll see your application working to bring in those modules into the node_modules directory that it creates.

Now that we have those, let’s set up our application in server.js.

Setting Up Our Node Application server.js

Since this is our starter kit for a single-page MEAN application, we are going to keep this simple. The entire code for the file is here and it is commented for help understanding.

server.js
    // modules =================================================
    var express        = require('express');
    var app            = express();
    var bodyParser     = require('body-parser');
    var methodOverride = require('method-override');

    // configuration ===========================================

    // config files
    var db = require('./config/db');

    // set our port
    var port = process.env.PORT || 8080;

    // connect to our mongoDB database
    // (uncomment after you enter in your own credentials in config/db.js)
    // mongoose.connect(db.url);

    // get all data/stuff of the body (POST) parameters
    // parse application/json
    app.use(bodyParser.json());

    // parse application/vnd.api+json as json
    app.use(bodyParser.json({ type: 'application/vnd.api+json' }));

    // parse application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({ extended: true }));

    // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT
    app.use(methodOverride('X-HTTP-Method-Override'));

    // set the static files location /public/img will be /img for users
    app.use(express.static(__dirname + '/public'));

    // routes ==================================================
    require('./app/routes')(app); // configure our routes

    // start app ===============================================
    // startup our app at http://localhost:8080
    app.listen(port);

    // shoutout to the user
    console.log('Magic happens on port ' + port);

    // expose app
    exports = module.exports = app;

We have now pulled in our modules, configured our application for things like database, some express settings, routes, and then started our server. Notice how we didn’t pull in mongoose here. There’s no need for it yet. We will be using it in our model that we will define soon.

Let’s look at config, a quick model, and routes since we haven’t created those yet. Those will be the last things that the backend side of our application needs.

Config config/

I know it doesn’t seem like much now since we only are putting the db.js config file here, but this was more for demonstration purposes. In the future, you may want to add more config files and call them in server.js so this is how we will do it.

config/db.js
        module.exports = {
            url : 'mongodb://localhost/stencil-dev'
        }

Now that this file is defined and we’ve called it in our server.js using var db = require('./config/db');, you can call any items inside of it using db.url.

For getting this to work, you’ll want a local MongoDB database installed or you can just grab a quick one-off service like Modulus or Mongolab. Just go ahead and create an account at one of those, create a database with your own credentials, and you’ll be able to get the URL string to use in your own config file.

Next up, we’ll create a quick Mongoose model so that we can define our Nerds in our database.

Nerd Model app/models/nerd.js

This will be all that is required to create records in our database. Once we define our Mongoose model, it will let us handle creating, reading, updating, and deleting our nerds.

Let’s go into the app/models/nerd.js file and add the following:

app/models/nerd.js
    // grab the mongoose module
    var mongoose = require('mongoose');

    // define our nerd model
    // module.exports allows us to pass this to other files when it is called
    module.exports = mongoose.model('Nerd', {
        name : {type : String, default: ''}
    });

This is where we will use the Mongoose module and be able to define our Nerd model with a name attribute with data type String. If you want more fields, feel free to add them here. Read up on the Mongoose docs to see all the things you can define.

Let’s move onto the routes and use the model we just created.

Node Routes app/routes.js

In the future, you can use the app folder to add more models, controllers, routes, and anything backend (Node) specific to your app.

Let’s get to our routes. When creating a single-page application, you will usually want to separate the functions of the backend application and the frontend application as much as possible.

Separation of Routes

To separate the duties of the separate parts of our application, we will be able to define as many routes as we want for our Node backend. This could include API routes or any other routes of that nature.

We won’t be diving into those since we’re not really handling creating an API or doing CRUD in this tutorial, but just know that this is where you’d handle those routes.

We’ve commented out the place to put those routes here.

app/routes.js
    // grab the nerd model we just created
    var Nerd = require('./models/nerd');

        module.exports = function(app) {

            // server routes ===========================================================
            // handle things like api calls
            // authentication routes

            // sample api route
            app.get('/api/nerds', function(req, res) {
                // use mongoose to get all nerds in the database
                Nerd.find(function(err, nerds) {

                    // if there is an error retrieving, send the error.
                                    // nothing after res.send(err) will execute
                    if (err)
                        res.send(err);

                    res.json(nerds); // return all nerds in JSON format
                });
            });

            // route to handle creating goes here (app.post)
            // route to handle delete goes here (app.delete)

            // frontend routes =========================================================
            // route to handle all angular requests
            app.get('*', function(req, res) {
                res.sendfile('./public/views/index.html'); // load our public/index.html file
            });

        };

This is where you can handle your API routes. For all other routes (*), we will send the user to our frontend application where Angular can handle routing them from there.

Backend Done!

Now that we have everything we need for our server to get set up! At this point, we can start our server, send a user the Angular app (index.html), and handle 1 API route to get all the nerds.

Let’s create that index.html file so that we can test out our server.

Create an Index View File public/views/index.html

Let’s just open up this file and add some quick text so we can test our server.

public/views/index.html
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">

        <title>Starter MEAN Single Page Application</title>

    </head>
    <body>

        we did it!

    </body>
    </html>

Test Our Server

With all the backend (and a tiny frontend piece) in place, let’s start up our server. Go into your console and type:

  1. node server.js

Now we can go into our browser and see http://localhost:8080 in action.

So simple, and yet so beautiful. Now let’s get to the frontend single-page AngularJS stuff.

The Frontend AngularJS

With all of our backend work in place, we can focus on the frontend. Our Node backend will send any user that visits our application to our index.html file since we’ve defined that in our catch-all route (app.get('*')).

The frontend work will require a few things:

  • Files and libraries brought in by Bower
  • Angular application structure (controllers, services)
  • We will create 3 different pages (Home, Nerds, Geeks)
  • Handle Angular routes using ngRoute so there are no page refreshes
  • Make it pretty with Bootstrap

Bower and Pulling in Components

We will need certain files for our application like bootstrap and of course angular. We will tell bower to grab those components for us.

Bower is a great frontend tool to manage your frontend resources. You just specify the packages you need and it will go grab them for you. Here’s an article on getting started with bower.

First, we will need Bower installed on our machine. Just type in npm install -g bower into your console.

After you have done that, you will now have access to bower globally on your system. We will need 2 files to get Bower working for us (.bowerrc and bower.json). We’ll place both of these in the root of our document.

.bowerrc will tell Bower where to place our files:

    {
        "directory": "public/libs"
    }

bower.json is similar to package.json and will tell Bower which packages are needed.

    {
        "name": "starter-node-angular",
        "version": "1.0.0",
        "dependencies": {
            "bootstrap": "latest",
            "font-awesome": "latest",
            "animate.css": "latest",
            "angular": "latest",
            "angular-route": "latest"
        }
    }

Let’s run it! In your console, in the root of your application, type:

  1. bower install

You can see bower pull in all the files we needed and now we have them in public/libs!

Now we can get down to business and work on our Angular stuff.

Setting Up Our Angular Application

For our Angular application, we will want:

  • 2 different pages (Home, Nerds)
  • A different Angular controller for each
  • An Angular service for Nerds
  • No page refresh when switching pages

Let’s create the files needed for our Angular application. This will be done in public/js. Here is the application structure for our frontend:

        - public
        ----- js
        ---------- controllers
        -------------------- MainCtrl.js
        -------------------- NerdCtrl.js
        ---------- services
        -------------------- NerdService.js
        ---------- app.js
        ---------- appRoutes.js

Once we have created our controllers, services, and routes, we will combine them all and inject these modules into our main app.js file to get everything working together.

Angular Controllers

We won’t go too far in-depth here so let’s just show off all three of our controllers and their code.

public/js/controllers/MainCtrl.js
    angular.module('MainCtrl', []).controller('MainController', function($scope) {

        $scope.tagline = 'To the moon and back!';

    });
public/js/controllers/NerdCtrl.js
    angular.module('NerdCtrl', []).controller('NerdController', function($scope) {

        $scope.tagline = 'Nothing beats a pocket protector!';

    });

Of course in the future, you will be doing a lot more with your controllers, but since this is more about application setup, we’ll move onto the services.

Angular Services

This is where you would use $http or $resource to do your API calls to the Node backend from your Angular frontend.

public/js/services/NerdService.js
    angular.module('NerdService', []).factory('Nerd', ['$http', function($http) {

        return {
            // call to get all nerds
            get : function() {
                return $http.get('/api/nerds');
            },

            // these will work when more API routes are defined on the Node side of things

            // call to POST and create a new nerd
            create : function(nerdData) {
                return $http.post('/api/nerds', nerdData);
            },

            // call to DELETE a nerd
            delete : function(id) {
                return $http.delete('/api/nerds/' + id);
            }
        }

    }]);

That’s it for our services. The only function that will work in that NerdService is the get function. The other two are just placeholders and they won’t work unless you define those specific routes in your app/routes.js file. For more on building APIs, here’s a tutorial for Building a RESTful Node API.

These services will call our Node backend, retrieve data in JSON format, and then we can use it in our Angular controllers.

Angular Routes

Now we will define our Angular routes inside of our public/js/appRoutes.js file.

public/js/appRoutes.js
        angular.module('appRoutes', []).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {

        $routeProvider

            // home page
            .when('/', {
                templateUrl: 'views/home.html',
                controller: 'MainController'
            })

            // nerds page that will use the NerdController
            .when('/nerds', {
                templateUrl: 'views/nerd.html',
                controller: 'NerdController'
            });

        $locationProvider.html5Mode(true);

    }]);

Our Angular frontend will use the template file and inject it into the <div ng-view></div> in our index.html file. It will do this without a page refresh which is exactly what we want for a single page application.

For more information on Angular routing and templating, check out our other tutorial: Single Page Apps with AngularJS.

Updated View Files

With all of the Angular routing ready to go, we just need to create the view files and then the smaller template files (home.html, nerd.html, and geek.html) will be injected into our index.html file inside of the <div ng-view></div>.

Notice in our index.html file we are calling the resources we pulled in using bower.

public/index.html
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <base href="/">

        <title>Starter Node and Angular</title>

        <!-- CSS -->
        <link rel="stylesheet" href="libs/bootstrap/dist/css/bootstrap.min.css">
        <link rel="stylesheet" href="css/style.css"> <!-- custom styles -->

        <!-- JS -->
        <script src="libs/angular/angular.min.js"></script>
        <script src="libs/angular-route/angular-route.min.js"></script>

        <!-- ANGULAR CUSTOM -->
        <script src="js/controllers/MainCtrl.js"></script>
        <script src="js/controllers/NerdCtrl.js"></script>
        <script src="js/services/NerdService.js"></script>
        <script src="js/appRoutes.js"></script>
        <script src="js/app.js"></script>
    </head>
    <body ng-app="sampleApp" ng-controller="NerdController">
    <div class="container">

        <!-- HEADER -->
        <nav class="navbar navbar-inverse">
            <div class="navbar-header">
                <a class="navbar-brand" href="/">Stencil: Node and Angular</a>
            </div>

            <!-- LINK TO OUR PAGES. ANGULAR HANDLES THE ROUTING HERE -->
            <ul class="nav navbar-nav">
                <li><a href="/nerds">Nerds</a></li>
            </ul>
        </nav>

        <!-- ANGULAR DYNAMIC CONTENT -->
        <div ng-view></div>

    </div>
    </body>
    </html>


    <!-- public/views/home.html -->

    <div class="jumbotron text-center">
        <h1>Home Page 4 Life</h1>

        <p>{{ tagline }}</p>
    </div>


    <!-- public/views/nerd.html -->

    <div class="jumbotron text-center">
        <h1>Nerds and Proud</h1>

        <p>{{ tagline }}</p>
    </div>

Making It All Work Together

We have defined our resources, controllers, services, and routes and included the files in our index.html. Now let’s make them all work together.

Let’s set up our Angular app to use all of our components. We will use dependency injection and set up our Angular application.

public/js/app.js
    angular.module('sampleApp', ['ngRoute', 'appRoutes', 'MainCtrl', 'NerdCtrl', 'NerdService']);

Conclusion

Now we have an application that has a Node.js backend and an AngularJS frontend. We can use this foundation to build any sort of application moving forward. We can add authentication and CRUD functionality to create a good application.

Also, for those looking for this project with the addition of the Jade templating engine, Florian Zemke has created a Jade version at his GitHub repo.

Next Steps

Moving forward, I’d encourage you to take this and see if it fits your needs. The point of this was to have a foundation for starting applications so that we aren’t reinventing the wheel every time we start a new project.

This is a very barebones example and for something more in-depth, I’d encourage people to take a look at mean.io for a more in-depth starter application.

Check out the GitHub repo for this project and take from it what you need. Sound off in the comments if you have any questions about how to expand this into your own applications.

Starter Kit

We’ve put this tutorial together as a starter kit at the GitHub repo. We’ll keep adding features to it on request and any updates we think will be helpful for applications.

Hopefully, it will be a good foundation for any sort of Single Page MEAN Stack Application.

To Use the Starter App

  1. Download the code
  2. Install the npm modules: npm install
  3. Install the bower components: bower install
  4. Start the server: node server.js
  5. Visit the application in your browser at http://localhost:8080
  6. Use this starter kit to build any application you need.

Further Reading: When building MEAN stack apps, the backend Node application will usually be an API that we build. This will allow the Angular frontend to consume our API that we built through Angular services. The next step is to hash out building a Node API. This next tutorial will teach us that and then we can go further in-depth on how to build the frontend Angular application to consume our new API.

Want More MEAN?

This article is part of our Getting MEAN series. Here are the other articles.

  • Setting Up a MEAN Stack Single Page Application
  • Build a RESTful API Using Node and Express 4
  • Using GruntJS in a MEAN Stack Application

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Chris on Code

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel