An express/requirejs/grunt/bower project boilerplate
MIT License
A starter project for building modern JavaScript web applications.
This project is not intended for others to use, and thus I can offer no support. Feel free to have a look around and steal any code you like that isn't copyrighted.
I built this project as as a starter application for future web projects; as a reference; and as a means to learn new and exciting web technologies.
This project uses the following technologies:
git clone git://github.com/badsyntax/express-project-boilerplate.git
npm install
bower install
grunt compass
grunt uglify && grunt concat
node app.js
to boot up the basic applicationgrunt watch
task while developing, this will compile your sass when you make changesnode app.js
to start the applicationnodemon app.js
to start the application and reload the application when files changeThe application will perform different tasks based on the application environment.
You can access the environment value by calling app.get('env')
which will return either
'development' or 'production'.
By default, the application will run in development mode, but you can use the following command to test the application
in production mode: NODE_ENV=production node app.js
Run grunt
to run the default grunt tasks.
Here are the individual grunt tasks you can run:
grunt watch
grunt test
grunt compass
grunt uglify
grunt jshint
grunt jasmine
grunt format
grunt jsbeautifier
grunt sass-convert
This system extends express to provide a more verbose and automated MVC system. A router handler is used to route requests to controllers. Controllers create the ViewModels and handle user input. ViewModels retrieve data models and provide that data to the views.
Routes map urls to controllers. The default route will try to map all requests to the relevant controllers. Here's an example of this catch-all default route:
{
uri: '/:controller?/:action?/:id?',
defaults: {
controller: 'home',
action: 'index'
}
}
Here's an example of a custom route:
{
uri: '/post/:uri',
controller: 'post'
}
Controllers will handle the request and user input, as well as creating ViewModels. For requests that return markup, use the 'ControllerLayout', which will create a 'layout' viewmodel, and all other ViewModels are added to this layout ViewModel.
Here's an example of a custom 'home' controller:
var ControllerLayout = require('../lib/Controller/ControllerLayout');
var ViewModel = require('../lib/ViewModel');
function HomeController() {
ControllerLayout.apply(this, arguments);
this.layout.setGlobalData({
title: 'Home'
});
}
require('util').inherits(HomeController, ControllerLayout);
HomeController.prototype.actionIndex = function() {
this.layout.setData({
body: ViewModel.factory('pages/home').render()
});
};
Here's an example of how to use the default REST controller, for creating an API:
var ControllerREST = require('../lib/Controller/ControllerREST');
function ControllerAPI() {
ControllerREST.apply(this, arguments);
}
require('util').inherits(ControllerAPI, ControllerREST);
// GET request (list)
ControllerAPI.prototype.actionIndex = function() {
var response = JSON.stringify({
hello: 'world'
});
this.sendResponse(200, 'application/json', response);
};
// POST request (create)
ControllerAPI.prototype.actionPost = function() {
var response = JSON.stringify({
hello: 'world'
});
this.sendResponse(200, 'application/json', response);
};
// PUT request (update)
ControllerAPI.prototype.actionUpdate = function() {
var response = JSON.stringify({
hello: 'world'
});
this.sendResponse(200, 'application/json', response);
};
// DELETE request (delete)
ControllerAPI.prototype.actionDelete = function() {
var response = JSON.stringify({
hello: 'world'
});
this.sendResponse(200, 'application/json', response);
};
module.exports = ControllerAPI;
Every view should have an associated ViewModel. You should render markup from ViewModels instead of from the views directly.
Here's an example of a basic ViewModel. You need to set the view data using the 'setData' method:
function MyViewModel() {
ViewModel.apply(this, arguments);
this.setData({
data: this.getData()
});
}
require('util').inherits(MyViewModel, ViewModel);
MyViewModel.prototype.getData = function() {
return 'data';
};
You can retrieve data in the ViewModels asyncronously via Q promises.
function MyViewModel() {
ViewModel.apply(this, arguments);
this.setData({
people: this.getPeople()
});
}
require('util').inherits(MyViewModel, ViewModel);
MyViewModel.prototype.getPeople = function() {
var deferred = q.defer();
setTimeout(function() {
deferred.resolve([{
name: 'Richard',
surname: 'Willis'
}]);
}, 400);
return deferred.promise;
};
TODO
This is the recommended ST2 user settings:
{
"font_size": 11,
"tab_size": 2,
"translate_tabs_to_spaces": true,
"trim_automatic_white_space": true,
"trim_trailing_white_space_on_save": true,
"word_wrap": false
}