roosevelt

Roosevelt MVC web framework

Roosevelt MVC web framework

Roosevelt is a web application development framework based on Express. Roosevelt abstracts all the crusty boilerplate necessary to build a typical Express app and provides a uniform MVC structure for your app.

Named for the most badass President of all-time whose facial hair just so happens to look like a curly brace, Roosevelt's main goal is to be the easiest JS-based web framework to learn and use by setting sane defaults while also providing easy ways to override the defaults and tap into the full potential of Express.

By default Roosevelt integrates Teddy for HTML templating, LESS for CSS preprocessing, and Closure Compiler for JS minification. But you can use other templating systems, CSS preprocessors, or JS minifiers if you like, as Roosevelt is easy to configure.

Table of contents

Why use Roosevelt?

Roosevelt is easy to use and has a low learning curve, unlike many other popular 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.
  • Teddy HTML templates are much easier to read and maintain than popular alternatives.
  • LESS and Closure Compiler preconfigured out of the box to intelligently minify your external facing CSS and JS files.

Create and run a Roosevelt app

First you will need to install Node.js or io.js. Then you might need to install some other stuff depending on what operating system you're running.

Windows:

Mac:

Ubuntu:

  • Install build-essential: sudo apt-get install build-essential
  • You may also need to sudo apt-get remove gyp if you already have gyp installed. Ubuntu's gyp is incompatible with common JS modules.

If you intend to use Roosevelt's default JS minifier (Closure Compiler), then you should also make sure to install the Java JRE as well. If you don't, then Roosevelt will install it as a dependency of your app which will bloat the size of your app by several tens of megabytes.

Once you have a sane developmemt environment, you can proceed with the standard install procedure below.

First install the command line tool globally (may require admin or root privileges):

npm install -g mkroosevelt

Use the command line tool to create a sample app:

mkroosevelt create myapp

Inside your new myapp folder you'll find a bin directory with the following files:

mac.command
unix.sh
windows.bat

Open the one relevant to whichever operating system you're running. That will install all the dependencies and start your new app!

If you want to do that manually instead using the console, then change into your new app's directory and then install dependencies:

cd myapp
npm install

Then run your app:

node app.js

Run your app in production mode:

export NODE_ENV=production && node app.js

Run your app on two CPUs:

node app.js -cores 2

Run your app on all your CPUs:

node app.js -cores max

While developing your app, a more convenient way to run the app is to use the npm start script.

The npm start script will run your app through nodemon and will automatically restart whenever you modify any JS, JSON, LESS, or HTML files.

Make sure you install nodemon first via npm install -g nodemon (may require admin or root privileges) and then simply execute this command:

npm start

Default directory structure

  • app.js: main app file. Feel free to rename this, but make sure to update package.json's reference to it.
  • bin: folder with operating system-specfic executables for your app.
    • mac.command: open this in Mac OS X to start your app graphically.
    • unix.sh: open this in UNIX-like environments like Ubuntu or other Linux distros to start your app graphically.
    • windows.bat: open this in Windows to start your app graphically.
  • mvc: folder for models, views, and controllers.
    • controllers: folder for controller files.
    • models: folder for model files.
    • views: folder for view files.
  • node_modules: a standard folder where all modules your app depends on (such as Roosevelt) are installed to. This folder is created by the npm install command.
    • models: symlink to mvc/models so you can require('models/yourModel') anywhere in your code without specifying a relative path. Roosevelt will create this symlink for you.
  • package.json: a standard file for configuring your app.
  • public: all contents within this folder will be exposed as static files.
  • statics: folder for CSS, images, JS files, and other statics. Some of the contents of this folder are symlinked to from public, which you can configure (see below).
    • css: folder for CSS files.
    • images: folder for image files.
    • js: folder for JS files.
  • .gitignore: a standard file which contains a list of files and folders to ignore if your project is in a git repo.

The default .gitignore file contains many common important things to ignore, however you may need to tweak it to your liking before using a fresh Roosevelt app in your git repo.

Some notable things ignored by default and why:

  • public: It's recommended that you don't create files in this folder manually, but instead use the symlinksToStatics feature detailed below to expose folders in your statics directory via auto-generated symlinks.
  • .build: By default Roosevelt will compile LESS and JS files down to minified versions in statics/.build when the server starts. As such, it's not recommended to place files in the build directory manually.
  • node_modules: This folder will be auto-generated when you run the npm install step to set up your app. Since some modules you might include later in your app can be platform-specific and are compiled for your OS during the install step, it's generally not recommended to commit the node_modules folder to git.

Configure your app with parameters

Roosevelt is designed to have a minimal amount of boilerplate so you can focus on just writing your app. All parameters are optional. As such, by default, all that's in app.js is this:

require('roosevelt')().startServer();

Roosevelt will determine your app's name by examining "name" in package.json. If none is provided, it will use Roosevelt Express instead.

Inside app.js, you can pass any of the below optional parameters to Roosevelt via its constructor like so:

require('roosevelt')({
  paramName: 'paramValue',
  param2:    'value2',
  etc:       'etc'
}).startServer();

Each param can also be defined in package.json under "rooseveltConfig".

  • port: The port your app will run on. Can also be defined using NODE_PORT environment variable.
    • Default: 43711
  • localhostOnly: Listen only to requests coming from localhost in production mode. This is useful in environments where it is expected that HTTP requests to your app will be proxied through a more traditional web server like Apache or nginx. This setting is ignored in development mode.
    • Default: true
  • disableLogger: When this option is set to true, Roosevelt will not log HTTP requests to the console.
    • Default: false
  • multipart: Settings to pass along to formidable using formidable's API for multipart form processing. To disable multipart forms entirely, set this option to false.
    • Default: {'multiples': true}
  • maxLagPerRequest: Maximum amount of time in miliseconds a given request is allowed to take before being interrupted with a 503 error. (See node-toobusy) (Temporarily disabled)
    • Default: 2000 (2 seconds)
  • shutdownTimeout: Maximum amount of time in miliseconds given to Roosevelt to gracefully shut itself down when sent the kill signal.
    • Default: 30000 (30 seconds)
  • modelsPath: Relative path on filesystem to where your model files are located.
    • Default: mvc/models
  • modelsNodeModulesSymlink: Name of the symlink to make in node_modules pointing to your models directory. Set to false to disable making this symlink.
    • Default: models
  • viewsPath: Relative path on filesystem to where your view files are located.
    • Default: mvc/views
  • viewEngine: What templating engine to use, formatted as 'fileExtension: nodeModule'. Supply an array of engines to use in that format in order to make use of multiple templating engines. Each engine you use must also be marked as a dependency in your app's package.json. Whichever engine you supply first with this parameter will be considered the default. Set to none to use no templating engine.
    • Default: html: teddy
    • Also by default the module teddy is marked as a dependency in package.json.
  • controllersPath: Relative path on filesystem to where your controller files are located.
    • Default: mvc/controllers
  • error404: Relative path on filesystem to where your "404 Not Found" controller is located. If you do not supply one, Roosevelt will use its default 404 controller instead.
    • Default: 404.js
  • error5xx: Relative path on filesystem to where your "Internal Server Error" controller is located. If you do not supply one, Roosevelt will use its default controller instead.
    • Default: 5xx.jx
  • error503: Relative path on filesystem to where your "503 Service Unavailable" controller is located. If you do not supply one, Roosevelt will use its default 503 controller instead.
    • Default: 503.js
  • staticsRoot: Relative path on filesystem to where your static assets are located. By default this folder will not be made public, but is instead meant to store unprocessed or uncompressed source assets.
    • Default: statics
  • cssPath: Subdirectory within staticsRoot where your CSS files are located. By default this folder will not be made public, but is instead meant to store unminified CSS source files which will be minified and stored elsewhere when the app is started.
    • Default: css
  • cssCompiler: Which CSS preprocessor, if any, to use. Must also be marked as a dependency in your app's package.json. Set to none to use no CSS preprocessor.
    • Default: {nodeModule: 'roosevelt-less', params: {compress: true}}.
    • Also by default the module roosevelt-less is marked as a dependency in package.json.
  • cssCompilerWhitelist: Whitelist of CSS files to compile as an array. Leave undefined to compile all files.
    • Default:
  • cssCompiledOutput: Where to place compiled CSS files. This folder will be made public by default.
    • Default: .build/css
  • jsPath: Subdirectory within staticsRoot where your JS files are located. By default this folder will not be made public, but is instead meant to store unminified JS source files which will be minified and stored elsewhere when the app is started.
    • Default: js
  • jsCompiler: Which JS minifier, if any, to use. Must also be marked as a dependency in your app's package.json. Set to none to use no JS minifier.
    • Default: {nodeModule: 'roosevelt-closure', params: {compilation_level: 'ADVANCED_OPTIMIZATIONS'}}.
    • Also by default the module roosevelt-closure is marked as a dependency in package.json.
  • jsCompilerWhitelist: Whitelist of JS files to compile as an array. Leave undefined to compile all files.
    • Default:
  • jsCompiledOutput: Where to place compiled JS files. This folder will be made public by default.
    • Default: .build/js
  • publicFolder: All files and folders specified in this path will be exposed as static files.
    • Default: public
  • symlinksToStatics: Array of folders from staticsRoot to make symlinks to in your public folder, formatted as either 'linkName: linkTarget' or simply 'linkName' if the link target has the same name as the desired link name.
    • Default: ['css: .build/css', 'images', 'js: .build/js'] (whitespace optional)
  • versionedStatics: If set to true, Roosevelt will prepend your app's version number from package.json to your statics URLs. Versioning your statics is useful for resetting your users' browser cache when you release a new version.
    • Default: false
  • versionedCssFile: If enabled, Roosevelt will create a CSS file which declares a CSS variable exposing your app's version number from package.json. Enable this option by supplying an object with the member variables fileName and varName.
    • Default: .
    • Example usage: {fileName: 'version.less', varName: 'appVersion'}.
  • alwaysHostPublic: By default in production mode Roosevelt will not expose the public folder. It's recommended instead that you host the public folder yourself directly through another web server, such as Apache or nginx. However, if you wish to override this behavior and have Roosevelt host your public folder even in production mode, then set this setting to true.
    • Default: false

Roosevelt also provides a series of events you can attach code to by passing a function to the desired event as a parameter to Roosevelt's constructor like so:

require('roosevelt')({
  onServerStartfunction(app) { /* do something */ }
});
  • onServerInit(app): Fired when the server begins starting, prior to any actions taken by Roosevelt.
  • onServerStart(app): Fired when the server starts.
  • onReqStart(req, res, next): Fired at the beginning of each new request.
    • req: The request object created by Express.
    • res: The response object created by Express.
    • next: Callback to continue with the request. Must be called to continue the request.
  • onReqBeforeRoute(req, res, next): Fired just before executing the controller.
    • req: The request object created by Express.
    • res: The response object created by Express.
    • next: Callback to continue with the request. Must be called to continue the request.
  • onReqAfterRoute(req, res): Fired after the request ends.

Making controller files

Controller files are just standard Express routes. A route is the term Express uses for URL endpoints, such as http://yoursite/blog or http://yoursite/about.

To make a new controller, just make a new file in the controllers directory. For example:

module.exports = function(app) { // app is the Express app created by Roosevelt 
 
  // standard Express route 
  app.route('/about').get(function(reqres) {
  
    // load a data model 
    var model = require('models/dataModel');
    
    // render a Teddy template and pass it the model 
    res.render('about', model);
  });
};

Making model files

Since the above example requires a model file named dataModel, you will need to make that too. To do that, place a file named dataModel.js in mvc/models.

Here's a simple example dataModel.js data model:

module.exports = {some: 'data'};

Making view files

Views are Teddy templates. See the Teddy documentation for information about how to author Teddy templates.

You can also use different templating engines by tweaking Roosevelt's parameters (see above parameter documentation).

Express variables exposed by Roosevelt

Roosevelt supplies several variables to Express that you may find handy. Access them using app.get('variableName').

Express variableDescription
expressThe express module.
viewEngine e.g. teddy by defaultAny view engine(s) you define will be exposed as an Express variable. For instance, the default view engine is teddy. So by default app.get('teddy') will return the teddy module.
formidableThe formidable module. Used for handling multipart forms.
appNameThe name of your app derived from package.json. Uses "Roosevelt Express" if no name is supplied.
appVersionThe version number of your app derived from package.json.
appDirThe directory the main module is in.
packageThe contents of package.json.
staticsRootFull path on the file system to where your app's statics folder is located.
publicFolderFull path on the file system to where your app's public folder is located.
cssPathFull path on the file system to where your app's CSS source files are located.
jsPathFull path on the file system to where your app's JS source files are located.
cssCompiledOutputFull path on the file system to where your app's minified CSS files are located.
jsCompiledOutputFull path on the file system to where your app's minified JS files are located.
modelsPathFull path on the file system to where your app's models folder is located.
viewsPathFull path on the file system to where your app's views folder is located.
controllersPathFull path on the file system to where your app's controllers folder is located.
paramsThe params you sent to Roosevelt.
portPort Roosevelt is running on.

Additionally the Roosevelt constructor returns the following object:

Roosevelt objectDescription
expressAppThe Express app created by Roosevelt.
httpThe http module used to start the web server.
startServerCalls http.listen() to start the web server with Roosevelt's config.

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.

Contributing to Roosevelt

To contribute back to Roosevelt, fork this repo and clone it to your computer.

To run the unit tests on your code changes, run this command:

npm test

If you want to hack on the CLI tool, see mkroosevelt.

There is plenty of opportunity to help improve Roosevelt if you're interested in lending a hand. If you'd like to help, take a look at the open issues and submit a pull request!

License

All original code in Roosevelt is licensed under the Creative Commons Attribution 4.0 International License. Commercial and noncommercial use is permitted with attribution.