roosevelt.js
Roosevelt is a new web framework for Node.js which uses Teddy for HTML templating and LESS for CSS preprocessing.
Built on Express, Roosevelt is designed to abstract all the crusty boilerplate necessary to build a typical Express app, sets sane defaults with mechanisms for override, and provides a uniform MVC structure for your app based on EventEmitter.
Why use Roosevelt?
Roosevelt is easy to use and has a low learning curve, unlike many other popular Node.js-based web frameworks.
Reasons for this include:
- Minimal boilerplate to get started. All the magic of Express is preconfigured for you.
- Default directory structure is simple, but easily configured.
- Concise MVC architecture driven by EventEmitter.
- Teddy HTML templates are much easier to read and maintain than popular alternatives.
Make a Roosevelt app
Install the command line tool globally (may require sudo):
npm install -g roosevelt
Use the command line tool to create a sample app:
roosevelt create myapp
Change into your new app's directory and then install dependencies:
cd myapp
npm install
Run the app:
npm start
Default directory structure
app.js
: main app filemvc
: folder for models, views, and controllers
controllers
: folder for controller filesmodels
: folder for model filesviews
: folder for view files
statics
: folder for CSS, images, JS files, LESS files, and other statics
css
: folder for CSS filesi
: folder for image filesjs
: folder for JS filesless
: folder for LESS files
Minimal boilerplate
All that's in app.js is this:
global.app = require('roosevelt'), app({
});
Roosevelt is designed to have a minimal amount of boilerplate so you can focus on just writing your app. All parameters are optional.
Note: app
must be defined as a global variable so that your models and controllers can access its utility methods later.
Configure your app
Inside app.js
, you can pass any of the following optional parameters to Roosevelt:
Option | Description | Default |
---|
name | The name of your app. | Roosevelt Express |
---|
port | The port your app will run on. | 43711 |
---|
modelsPath | Path on filesystem to where your model files are located. | mvc/models |
---|
viewsPath | Path on filesystem to where your view files are located. | mvc/views |
---|
controllersPath | Path on filesystem to where your controller files are located. | mvc/controllers |
---|
staticsRoot | All files and folders specified in this path will be exposed as statics. | statics |
---|
imagesPath | Path on filesystem to where your image files are located. | statics/i |
---|
cssPath | Path on filesystem to where your CSS files are located. | statics/css |
---|
lessPath | Path on filesystem to where your LESS files are located. | statics/less |
---|
jsPath | Path on filesystem to where your JS files are located. | statics/js |
---|
staticsPrefix | String to prefix statics with in the URL (useful for versioning statics). | undefined |
---|
customConfigs | Use this to define a custom function to be executed during the Express config stage if you need one, e.g.
function() { put custom Express config code here } . | undefined |
---|
Defining routes (URL endpoints)
A route is the term Express uses for URL endpoints, such as http://yoursite/blog
or http://yoursite/about
.
The Roosevelt framework will automatically assign a route corresponding to the name of each file in your controllers directory. As such, to make a new route just make a new file in the controllers directory.
How to make a new controller file
Suppose we make a controller file called hello.js
. Because the controller's file name is hello.js
, Roosevelt will make a new URL endpoint http://yoursite/hello
on your app.
Here's some sample code for your controller:
module.exports = app.loadModel('helloModel');
app.on('helloReady', function(res, model) {
res.render('hello', model);
});
Here's a line-by-line explanation of how it works:
The first line module.exports = app.loadModel('helloModel');
explained:
- This line loads the
helloModel
data model. app.loadModel
is Roosevelt's method for loading a model from your models directory.helloModel
is the name of the model file we're loading in this example code.- Assigning
app.loadModel('helloModel')
to module.exports
allows Roosevelt to load and execute the code in your model file each time someone visits http://yoursite/hello
.
The next line app.on('helloReady', function(res, model) {
explained:
- This line listens for an event called
helloReady
which will be called later when you create your model. app.on
is an EventEmitter method which accepts two arguments: eventName
and listener
.helloReady
is the eventName
we will listen for.function(res, model) {
is the beginning of the listener
function that will be executed when the helloReady
event is fired.res
is the response object provided by Express.model
is the data model provided by helloModel
.
The last line res.render('hello', model);
explained:
- This line renders a template called
hello.html
when the helloReady
event is fired. res.render
is the template rendering method provided by Express. If no file extension is provided to the template name, Roosevelt will assume the extension is .html
.hello
is the name of the template file (sans file extension) to render.
How to make a new model file
Now that we've defined our hello.js
controller above, we need to make the helloModel
model file it references.
Here's a sample helloModel.js
:
var model = function(req, res) {
model.data = {some: 'data'};
app.emit('helloReady', res, model.data);
};
module.exports = model;
Here's a line-by-line explanation of how it works:
The first line var model = function(req, res) {
explained:
The next line model.data = {some: 'data'};
is just a sample model definition. In place of this in a real app you would probably have several lines of much more complex code defining model.data
by pulling data out of a database or from wherever your app's data is stored. How you deal with your app's data is up to you, but the code for it generally speaking should live in your model files.
The next line app.emit('helloReady', res, model.data);
explained:
- With the data model fully composed, this line emits the
helloReady event
, which the controller is listening for. app.emit
is an EventEmitter method which lets you emit arbitrary events at will.helloReady
is the name of the event to emit.res
is the response object provided by Express.model.data
is the data model to pass to the controller. Note: This must be an object, not a function.
The last line module.exports = model;
makes the model loadable by a controller.
How to make a new view
Views are Teddy templates. See the Teddy documentation for information about how to author Teddy templates.
How to use LESS with Roosevelt
Using LESS with Roosevelt is optional.
Roosevelt will automatically compile any (.less
) files in your LESS folder down to minified CSS (.css
) files of the same name in your CSS folder. Note: This will overwrite any preexisting CSS files of the same name, so be careful.
The CSS minifier used by LESS is YUI Compressor.
Objects exposed by Roosevelt
After you require('roosevelt')
, assign it to something like global.app
, and then call app()
, you might want to know what objects app()
exposes.
Here's a handy chart:
Object | Description |
---|
app | Your Roosevelt app. At a basic level, a Roosevelt app is just an Express app with some settings changed and with the new member objects and methods outlined below. |
---|
app.params | The list of parameters you passed to Roosevelt. |
---|
app.express | The Express object created by Roosevelt. |
---|
app.teddy | The Teddy object created by Roosevelt. |
---|
app.loadModel | Calling app.loadModel('modelName') will load a specified model from your models folder. |
---|
Paths exposed |
---|
app.appdir | Full path on the filesystem that the main module is located in. |
---|
app.modelsPath | Full path on the filesystem that the models directory is located in. |
---|
app.viewsPath | Full path on the filesystem that the views directory is located in. |
---|
app.controllersPath | Full path on the filesystem that the controllers directory is located in. |
---|
app.staticsRoot | Full path on the filesystem that the statics root directory is located in. |
---|
app.imagesPath | Full path on the filesystem that the images directory is located in. |
---|
app.cssPath | Full path on the filesystem that the CSS file directory is located in. |
---|
app.lessPath | Full path on the filesystem that the LESS file directory is located in. |
---|
app.jsPath | Full path on the filesystem that the client-side JS file directory is located in. |
---|
Event objects and methods |
---|
|
app.events | The Events object created by Roosevelt. |
---|
app.emitter | The EventEmitter object created by Roosevelt. |
---|
app.addListener | The addListener method bound to Roosevelt's EventEmitter object. |
---|
app.on | The on method bound to Roosevelt's EventEmitter object. |
---|
app.once | The once method bound to Roosevelt's EventEmitter object. |
---|
app.removeListener | The removeListener method bound to Roosevelt's EventEmitter object. |
---|
app.removeAllListeners | The removeAllListeners method bound to Roosevelt's EventEmitter object. |
---|
app.setMaxListeners | The setMaxListeners method bound to Roosevelt's EventEmitter object. |
---|
app.listeners | The listeners method bound to Roosevelt's EventEmitter object. |
---|
app.emit | The emit method bound to Roosevelt's EventEmitter object. |
---|
Warning: Roosevelt is beta software!
Not many apps have been written using Roosevelt yet, so it's entirely possible that there will be some significant bugs.
You should not use Roosevelt in production yet unless you're willing to devote some time to fixing any bugs you might find.
Help wanted!
Pull requests are welcome! Here are some things at the top of the to-do list at the moment:
- HTTPS support
- Support for more custom HTTP status code error pages
- Support for templating engines other than teddy
- Support for CSS preprocessors other than LESS
- Support for a client-side JS minifier (e.g. Google's Closure compiler)
- Probably many other things are needed too
Dependencies
- express - a minimal and flexible node.js web application framework
- teddy - an easy-to-read, HTML-based, mostly logic-less DOM templating engine
- less-middleware - Connect middleware for LESS compiling
- wrench - used by the CLI tool to help you create your sample app
License
All original code in Roosevelt is licensed under the Creative Commons Attribution 3.0 Unported License. Commercial and noncommercial use is permitted with attribution.