Roosevelt is a web application development framework based on Express. Roosevelt abstracts all the crusty boilerplate necessary to build a typical web application using Express 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.
Roosevelt will also automatically validate your HTML using a local instance of the Nu HTML Checker.
- Why use Roosevelt
- Create and run a Roosevelt app
- Default directory structure
- Configure your app with parameters
- Making controller files
- Making model files
- Making view files
- Express variables exposed by Roosevelt
- Express middleware and other configurations automatically provided by Roosevelt
- Warning: Roosevelt is beta software!
- Contributing to 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.
- Automatic HTML validation.
- LESS and Closure Compiler preconfigured out of the box to intelligently minify your external facing CSS and JS files.
First you will need to install Node.js and the Java JDK. (The JDK is required for the local HTML validator feature.)
If this is your first time running a Node.js application, be sure to follow npm's instructions for setting npm permissions correctly so you can run npm commands without elevated privileges.
Then you might need to install some other stuff depending on what operating system you're running.
Some dependencies require Python or a C++ compiler. The procedure for getting these on your system varies by operating system:
Windows:
- Install python 2.7.6 (not 3.x, that doesn't work). Download that here.
- Add python to your PATH. Instructions for that are here.
- Install Visual Studio (payware) or Visual Studio Express for Windows Desktop (registerware): Download that here.
- Windows users are advised to run their command line as administrator due to symlink creation requiring elevated command prompt in Windows.
Mac:
- Install Xcode.
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.
Once you have a sane developmemt environment, you can proceed with the standard install procedure below.
Globally install Yeoman.
npm i -g yo
Globally install Roosevelt Yeoman generator.
npm i -g generator-roosevelt
Create a Roosevelt app.
yo roosevelt
Then follow the prompts.
Afterward:
Install dependencies.
npm i
Run in development mode.
npm run dev
Or run in production mode:
npm run prod
Note: npm start
is aliased to npm run prod
.
Run your app with an attached HTML validator (HTML validator is attached by default):
npm run dev attach
Run your app with a detached HTML validator (runs validator as a separate process in the background; process must be manually killed later, see below):
npm run dev detach-validator
After running your app with a detached HTML validator, use this command to shut down the HTML validator:
npm run kill-validator
Run your app on two CPUs:
node app.js -cores 2
Run your app on all your CPUs (this is the default behavior):
node app.js -cores max
Remove all symlinks and directories generated by Roosevelt:
npm run cleanup
Scan current package.json Roosevelt configuration and warn about any issues:
npm run audit
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.
lib
: Optional folder for any modules, utility libraries, or other dependencies your app may require which aren't in npm.node_modules
: a standard folder where all modules your app depends on (such as Roosevelt) are installed to. This folder is created by thenpm install
command.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 thesymlinksToStatics
feature detailed below to expose folders in yourstatics
directory via auto-generated symlinks..build
: By default Roosevelt will compile LESS and JS files down to minified versions instatics/.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 thenpm 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 thenode_modules
folder to git.
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"
.
appDir
: Useful to change when using a test environment like Mocha or if you just want to specify it by hand.- Default: The directory where your project package.json is located.
{appDir: 'User/Path/to/project'}
- Default: The directory where your project package.json is located.
port
: The port your app will run on. Can also be defined usingHTTP_PORT
orNODE_PORT
environment variable.- Default:
43711
- Default:
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
- Default:
disableLogger
: When this option is set to true, Roosevelt will not log HTTP requests to the console.- Default:
false
- Default:
noMinify
: Disables HTML minification as well as the minification step in (supporting) CSS and JS compilers. Automatically enabled during dev mode. Can also be passed as the command line argument-no-minify
.- Default:
false
- Default:
enableValidator
: Enables or disables the built-in HTML validator in dev mode.- Default:
false
- e.g. force validator off in dev mode regardless of app settings:
npm run dev disable-validator
- e.g. force validator on in prod mode regardless of app settings:
npm run dev enable-validator
- Default:
htmlValidator
: Params to send to html-validator (ifenableValidator
is set to true). WhensuppressWarnings
is set to true validation warnings will be hidden and only errors will be shown. WhenseparateProcess
is set to true the HTML validator will run separately from the node process.- Default:
{port: '8888', separateProcess: false, format: 'text', suppressWarnings: false}
- Can be disabled for individual requests by sending the request header
Partial
with the value set totrue
or by passing_disableValidator
to the model and setting it totrue
.
- Default:
validatorExceptions
: Use this to customize the name of the request header or model value that is used to disable the HTML validator.- Default:
{'requestHeader': 'Partial', 'modelValue': '_disableValidator'}
- Default:
multipart
: Settings to pass along to formidable using formidable's API for multipart form processing. Access files uploaded in your controllers by examining thereq.files
object. Roosevelt will remove any files uploaded to theuploadDir
when the request ends automatically. To keep any, be sure to move them before the request ends. To disable multipart forms entirely, set this option to false.- Default:
{'multiples': true}
- Default:
maxLagPerRequest
: Maximum amount of time in miliseconds a given request is allowed to take before being interrupted with a 503 error. (See node-toobusy)- Default:
70
(70ms)
- Default:
shutdownTimeout
: Maximum amount of time in miliseconds given to Roosevelt to gracefully shut itself down when sent the kill signal.- Default:
30000
(30 seconds)
- Default:
bodyParserUrlencodedParams
: Supply parameters to body-parser.urlencoded.- Default:
{extended: true}
- Default:
bodyParserJsonParams
: Supply parameters to body-parser.json.- Default:
{}
- Default:
suppressLogs
: When this option is set to true, Roosevelt will not log app status to the console. Useful when running Roosevelt in a testing context.- Default:
false
- Default:
https
: Run an HTTPS server using Roosevelt.- Default:
false
- Default:
httpsOnly
: If running an HTTPS server, determines whether or not the default HTTP server will be disabled- Default:
false
- Default:
httpsPort
: The port your app will run a HTTPS server on, if enabled. Can also be defined usingHTTPS_PORT
environment variable.- Default:
43733
- Default:
pfx
: Specify whether or not your app will use pfx or standard certification.- Default:
false
- Default:
keyPath
: Stores the file paths of specific key/certificate to be used by the server.- Object values:
pfx
,key
,cert
-- use one of {pfx
} or {key
,cert
} - Default:
null
- Object values:
passphrase
: Supply the HTTPS server with the password for the certificate being used, if necessary.- Default:
null
- Default:
ca
: Certificate authority to match client certificates against, as a file path or array of file paths.- Default:
null
- Default:
requestCert
: Request a certificate from a client and attempt to verify it.- Default:
false
- Default:
rejectUnauthorized
: Upon failing to authorize a user with supplied CA(s), reject their connection entirely.- Default:
false
- Default:
modelsPath
: Relative path on filesystem to where your model files are located.- Default:
mvc/models
- Default:
viewsPath
: Relative path on filesystem to where your view files are located.- Default:
mvc/views
- Default:
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 tonone
to use no templating engine.- Default:
html: teddy
- Also by default the module teddy is marked as a dependency in package.json.
- Default:
controllersPath
: Relative path on filesystem to where your controller files are located.- Default:
mvc/controllers
- Default:
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
- Default:
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
- Default:
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
- Default:
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
- Default:
htmlMinify
: Configuration for html-minifier. Setoverride
tofalse
to disable minification entirely. Setexception_url
to disable for specific routes. UsehtmlMinifier
to pass supported parameters to html-minifier.- Default: "htmlMinify": {'override': true, 'exception_url': false, 'htmlMinifier': {'html5': true}}
cssPath
: Subdirectory withinstaticsRoot
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
- Default:
cssCompiler
: Which CSS preprocessor, if any, to use. Must also be marked as a dependency in your app's package.json. Set tonone
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.
- Default:
cssCompilerWhitelist
: Whitelist of CSS files to compile as an array. Leave undefined to compile all files.- Default:
undefined
- Default:
cssCompiledOutput
: Where to place compiled CSS files. This folder will be made public by default.- Default:
.build/css
- Default:
jsPath
: Subdirectory withinstaticsRoot
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
- Default:
bundledJsPath
: Subdirectory withinjsPath
where you would like browserify to deposit bundled JS files it produces (if you use browserify).- Default:
.bundled
- Default:
exposeBundles
: Whether or not to copy thebundledJsPath
directory to your build directory (defined below injsCompiledOutput
).- Default:
true
- Default:
browserifyBundles
: Declare browserify bundles: one or more files in yourjsPath
for browserify to bundle via its bundle method. Use of browserify is optional. If no bundles are defined here, the browserify step will be skipped.- Default:
[]
- Example declaring one bundle:
[{outputFile: "bundle.js", files: ["landingPage.js", "main.js", "etc.js"], params: {someOpt: "someValue"}}]
- Example declaring one bundle only used in dev mode
[{outputFile: "bundle.js", env: "dev", files: ["landingPage.js", "main.js", "etc.js"], params: {someOpt: "someValue"}}]
- Example declaring multiple bundles:
[{outputFile: "bundle1.js", files: ["landingPage.js", "main.js", "etc.js"], params: {someOpt: "someValue"}}, {outputFile: "bundle2.js", files: ["somethingElse.js", "anotherThing.js", "etc.js"]}, etc...]
- Note: Omitting
env
will result in bundling in both modes. - Note:
params
is optional. If it is not set, these default params will be sent:{paths: yourJsPath}
- Default:
jsCompiler
: Which JS minifier, if any, to use. Must also be marked as a dependency in your app's package.json. Set tonone
to use no JS minifier.- Default:
{nodeModule: "roosevelt-closure", showWarnings: false, params: {compilationLevel: "ADVANCED"}}
. - Also by default the module roosevelt-closure is marked as a dependency in package.json.
- Note: Set
showWarnings
totrue
to display compiler warnings.
- Default:
jsCompilerWhitelist
: Whitelist of JS files to compile as an array. Leave undefined to compile all files. Supply a:
character after each file name to delimit an alternate file path and/or file name for the minified file.- Default:
undefined
- Example:
library-name/example.js:lib/example.min.js
(customizes both file path and file name of minified file)
- Default:
jsCompiledOutput
: Where to place compiled JS files. This folder will be made public by default.- Default:
.build/js
- Default:
nodeEnv
: Param to override theNODE_ENV
environment variable.- Default:
undefined
- Default:
publicFolder
: All files and folders specified in this path will be exposed as static files.- Default:
public
- Default:
favicon
: Location of your favicon file.- Default:
images/favicon.ico
- Disable favicon support by supplying
none
to this parameter.
- Default:
symlinksToStatics
: Array of folders fromstaticsRoot
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)
- Default:
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
- Default:
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 variablesfileName
andvarName
.- Default:
undefined
. - Example usage:
{fileName: '_version.less', varName: 'appVersion'}
.
- Default:
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
- Default:
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')({
onServerStart: function(app) { /* do something */ }
});
onServerInit(app)
: Fired when the server begins starting, prior to any actions taken by Roosevelt.app
: The Express app created by Roosevelt.
onServerStart(app)
: Fired when the server starts.app
: The Express app created by Roosevelt.
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.req
: The request object created by Express.res
: The response object created by Express.
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(req, res) {
// load a data model
var model = require('models/dataModel');
// render a Teddy template and pass it the model
res.render('about', model);
});
};
Sometimes it is also useful to separate controller logic from your routing. This can be done by creating a reusable controller module.
A typical example would be creating a reusable controller for "404 not found" pages:
// reusable controller "notFound.js"
module.exports = function(app, req, res) {
var model = { content: 'Cannot find this page' };
res.status(404);
res.render('404', model);
}
Reusable controller modules differ from standard controller modules in that they accept req
and res
arguments in addition to app
. They are meant to be called from within routes rather than define new routes.
This allows them to be called at will in any other controller's route when needed:
// import the "notFound" controller logic previously defined
var throw404 = require('controllers/notFound');
module.exports = function(app) {
app.route('/whatever').get(function(req, res) {
// test some logic that could fail
// thus triggering the need for the 404 controller
if (something) {
// logic didn't fail
// so just render the page normally
var model = require('models/dataModel');
res.render('whatever', model);
}
else {
// logic failed
// so throw the 404 by executing your reusable controller
throw404(app, req, res);
}
});
};
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'};
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).
Roosevelt supplies several variables to Express that you may find handy. Access them using app.get('variableName')
.
Express variable | Description |
---|---|
express |
The express module. |
viewEngine e.g. teddy by default |
Any 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. |
formidable |
The formidable module. Used for handling multipart forms. |
appName |
The name of your app derived from package.json . Uses "Roosevelt Express" if no name is supplied. |
appVersion |
The version number of your app derived from package.json . |
appDir |
The directory the main module is in. |
package |
The contents of package.json . |
staticsRoot |
Full path on the file system to where your app's statics folder is located. |
publicFolder |
Full path on the file system to where your app's public folder is located. |
cssPath |
Full path on the file system to where your app's CSS source files are located. |
jsPath |
Full path on the file system to where your app's JS source files are located. |
cssCompiledOutput |
Full path on the file system to where your app's minified CSS files are located. |
jsCompiledOutput |
Full path on the file system to where your app's minified JS files are located. |
modelsPath |
Full path on the file system to where your app's models folder is located. |
viewsPath |
Full path on the file system to where your app's views folder is located. |
controllersPath |
Full path on the file system to where your app's controllers folder is located. |
params |
The params you sent to Roosevelt. |
port |
Port Roosevelt is running on. |
suppressLogs |
Whether or not Roosevelt is suppressing console logging. |
Additionally the Roosevelt constructor returns the following object:
Roosevelt object | Description |
---|---|
expressApp |
The Express app created by Roosevelt. |
httpServer |
The http server created by Roosevelt. httpServer is also available as a direct child of app , e.g. app.httpServer . |
httpsServer |
The https server created by Roosevelt. httpsServer is also available as a direct child of app , e.g. app.httpsServer . |
initServer |
Starts the HTML validator, sets up some middleware, runs the CSS and JS preprocessors, and maps routes, but does not start the HTTP server. Call this method manually first instead of startServer if you need to setup the Express app, but still need to do additional setup before the HTTP server is started. This method is automatically called by startServer once per instance if it has not yet already been called. |
startServer |
Calls the listen method of http , https , or both (depending on your configuration) to start the web server with Roosevelt's config. |
In addition to exposing a number of variables to Express and providing the MVC interface outlined above, Roosevelt also:
- Includes the compression middleware.
- Includes the cookie-parser middleware.
- Disables
x-powered-by
andetag
. - Logs HTTP requests to the console using morgan, specifically
morgan('combined')
. - Includes the body-parser middleware with
bodyParser.json
andbodyParser.urlencoded({extended: true})
. - Includes the method-override middleware.
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.
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 generator-roosevelt.
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!