Simple Node.js Express MVR Template
In this post we’ll walk through how to setup a simple MVR Node.js project using Express, Mongoose (MongoDB), Jade (templating) and everyauth (authentication). First off, what the fuck is MVR, think MVC but with routes instead controllers.
What we’re going to be using
- Express for our framework
- Mongoose for MongoDB
- Jade for templating
- everyauth for authentication
- Twitter Bootstrap for styling
Setup
You’re going to need Node.JS, NPM, and MongoDB installed. If you haven’t done that yet see Building and Installing Node.js and MongoDB Quickstart.
Open up the command line to create the project
$ npm install -g express-generator
$ express examplemvr
$ cd examplemvr
$ rm -rf ./routes
$ rm public/stylesheets/style.css
$ mkdir models
$ npm install
Now open the mongo console and insert some test data
$ mongo nodemvr
$ db.examples.insert({name:'Test Doc'});
Dependencies
Open the examplemvr project in your favorite text editor and edit package.json to match the following
package.json
--------------
{
"name": "application-name"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.8"
, "jade": ">= 0.0.1"
, "mongodb": ">= 0.9.6-7"
, "mongoose": ">= 2.5.10"
, "everyauth": ">=0.2.32"
},
"engines": {
"node": ">= 0.6.14",
"npm": "1.0.x"
}
}
This tells NPM what modules we need and the versions we require. Now open up the command line again to update your modules with NPM
$ npm install
This will tell NPM to read the package.json and install any dependencies that are needed.
Application Core
Now open app.js and edit it to match the following
/app.js
--------------
var express = require('express');
var app = module.exports = express.createServer();
app.everyauth = require('everyauth');
app.everyauth.helpExpress(app);
app.mongoose = require('mongoose');
var config = require('./config.js')(app, express);
var models = {};
models.examples = require('./models/example')(app.mongoose).model;
require('./routes')(app, models);
app.listen(process.env.PORT || 3000);
# Review
Let’s review this a few lines at a time.
Require express and assign the server to the “app” object.
var express = require('express');
var app = module.exports = express.createServer();
Require everyauth and load the helpers
app.everyauth = require('everyauth');
app.everyauth.helpExpress(app);
Require mongoose
app.mongoose = require('mongoose');
Require the config file and pass it some variables to use, we’ll go through this later
var config = require('./config.js')(app, express);
Create the object to hold our models and then require them (is this example we only have 1 model)
var models = {};
models.examples = require('./models/example')(app.mongoose).model;
Require the routes
require('./routes')(app, models);
Set the server to listen on a port (process.env.PORT is for production deployment, ie heroku)
app.listen(process.env.PORT || 3000);
Setup the config
Create a new file under the root of the project named “config.js” and edit it to match the following
/config.js
--------------
module.exports = function(app, express, mongoose){
var config = this;
app.requireAuth = true;
//configure everyauth
app.everyauth.twitter
.consumerKey('yourKey')
.consumerSecret('yourSecret')
.findOrCreateUser( function (session, accessToken, accessTokenSecret, user) {
return 1;
}).redirectPath('/');
//generic config
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'topsecret' }));
app.use(app.everyauth.middleware());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
//env specific config
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
app.mongoose.connect('mongodb://localhost/nodemvr');
});
app.configure('production', function(){
app.use(express.errorHandler());
app.mongoose.connect('mongodb://flame.mongohq.com:27087/nodemvr');
});
return config;
};
I’ll let you spend some time to figure out what each little bit of this does but the gist of it is that it sets up your twitter information for authentication and then various config settings which should be pretty self explanitory.
NOTE - you will need to setup an application on dev.twitter.com to obtain a key and secret if you want to use authentication. If not, just set app.requireAuth = false.
Models
Now let’s create out example model. We’re going to be using Mongoose for MongoDB.
/models/example.js
--------------
module.exports = function(mongoose) {
var collection = 'examples';
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var schema = new Schema({
author: ObjectId,
name: String,
date: Date
});
this.model = mongoose.model(collection, schema);
return this;
};
Set your collection and build out you’re schema.
Views
Edit the index.jade and layout.jade to match the following
/views/layout.jade
--------------
!!!
html
head
title= title
link(rel='stylesheet', href='/stylesheets/bootstrap.min.css')
body
div.topbar.navbar.navbar-fixed-top
div.fill
div.container
a(href='/').brand #{title}
div.container!= body
footer
p
| Node.js MVC template by
a(href='http://benedmunds.com')(target='_blank') Ben Edmunds
/views/index.jade
--------------
div.hero-unit
h1 Heading
div.content
div.row
div.span12
h2 Sub-Heading
ul.unstyled.indent
each example in examples
li
a(href="example/#{example._id}") #{example.name}
We’ll be using twitter’s bootstrap for our styling so go grab the img, and js from Github and we’ll use a customized version of the spacelab theme for bootstrap which you can get from Gist. Place them under their respective folder in the public directory. Your new directory structure should look like the following
public/
- images/
glyphicons-halflings-white.png
glyphicons-halflings.png
- javascripts/
bootstrap.min.js
- stylesheets/
bootstrap.min.css
Routes
Now for the final step we’re going to create the routes to glue this all together, in the root of your project create a file named “routes.js” and insert the following
/routes.js
--------------
module.exports = function(app, models){
app.get('/', function(req, res){
if (app.requireAuth === true && req.loggedIn === false)
res.redirect('/auth/twitter');
//get all the rides
models.examples.find({}, function(err, docs){
//render the index page
res.render('index.jade', {
locals: {
title: 'Example',
search_placeholder: 'Search',
examples: docs
}
});
});
});
};
# Review
We’ll walk through this one in more detail.
Create a route to respond to /
module.exports = function(app, models){
app.get('/', function(req, res){
If requireAuth is true in our config then require authentication
if (app.requireAuth === true && req.loggedIn === false)
res.redirect('/auth/twitter');
Get the example data from the model
models.examples.find({}, function(err, docs){
Render the index.jade template with our data
res.render('index.jade', {
locals: {
title: 'Example',
search_placeholder: 'Search',
examples: docs
}
});
Done!
Open the command line and start your app
$ node app.js
Get the code
You can get the code for this project on Github. I’m fairly new to node and this is a work in progress so if you see anywhere this can be improved feel free to send a pull request.
Translations
This page has been translated into Spanish language by Maria Ramos from Webhostinghub.com/support/edu.
Have fun!
Want to Learn More about Node?
Buy the Book