12factor.net web app platform for node.js, built on express 3
We are porting our 2-year evolved boilerplate from Skookum Digital Works into this project. Expect lots of updates!
$ sudo npm install -g base12
$ base12 new projectname && cd projectname
$ node run
Production-ready
- Painlessly follow Ryan Dahl's 'gospel' for node.js apps (12factor.net by Adam Wiggins).
Cloud Deployments
- Deploy to the cloud easily, out-of-the-box (supports joyent, amazon, linode, rackspace; TODO: heroku, nodejitsu).
Structure
- Always know where things go. A proven MVC architecture on top of express.
Express 3
- Leverage the newest version of the most popular app framework for node.js.
Not Rails
- We believe that, if Rails is best for your project, you should use it. Instead, base12 embraces the node.js way: light processes, shallow inheritance, simple interfaces, and the chain-of-responsibility pattern.
app
/controllers -- controllers are automatically loaded (user.js -> app.controllers.user)
/lib -- app-specific modules (default: routes.js, middleware.js, locals.js)
/middleware -- middleware is automatically loaded (auth.js -> app.middleware.auth)
/models -- models are automatically loaded (project.js -> app.models.project)
/public -- static files are hosted here
/shared -- isomorphic (client/server) files are hosted here
/views -- view templates are automatically loaded via express
index.js -- starts your application with `base12.app()`
doc -- documentation
env -- named environment configurations (eg `staging`, `deployment`)
lib -- non-npm-published node.js libraries
scripts -- scripts (eg admin, deployment, migrations)
test -- tests (vows by default)
tmp -- your app can store temporary files here
package.json -- npm package.json (base12 app `constants` stored here)
.env.js -- environment config (created by `npm install`)
build.js -- builds assets
run.js -- runs your app
cycle.js -- watches local files and builds/runs on changes (for development)
When base12 starts, it runs /index.js
, which uses base12.balance()
to balance app processes via cluster
(1 process per cpu).
Each process runs /app/index.js
, which creates a new app with base12.app()
. The app
instance is passed into all modules.
Once all modules have run, the app starts listening for requests.
All base12 modules have the same signature:
module.exports = function(app) {
// ...
return my_module;
}
Application constants (values that do not change from machine to machine) are located under constants
in package.json.
Base12 also pulls the project name
from the default package.json structure:
"name":"base12app",
"constants": {
"title": "node.js 12-factor app",
"session_length": 1209600000,
"request_timeout": 10000
}
Environment config (values that can change from machine to machine) are located in .env.js
, which is not tracked by git.
Running npm install
will provide you with a default .env.js from env/default.env.js if one does not already exist.
module.exports = {
view_engine: 'jade',
view_options: { layout: false },
port: 3000,
timeout: 10000,
cookie_secret: 'mysecret',
session: {
key: 'mykey'
},
redis: {
host: 'localhost',
port: 6379
}
};
base12.app() augments express() with a thin layer of auto-loaded hashes:
-
app.models (from app/models)
-
app.controllers (from app/controllers)
-
app.middleware (from app/middleware)
-
app.constants (from package.json)
-
app.config (from .env.js)
Otherwise, base12.app()
is just like express()
.
$ npm install
$ node build
$ node run
$ node run 1
$ node cycle
$ npm run-script lock
"One codebase tracked in version control, many deploys."
Base12 uses git-based deployments exclusively.
"Explicitly declare and isolate dependencies."
Base12 uses npm install
both locally and in deploys to manage dependencies.
Manage your dependencies in package.json
.
"Store config in the environment."
Base12 uses the untracked .env.js file to manage environment config. Once tooling is better supported on hosts, it will likely move to environment variables.
"Treat backing services as attached resources."
Backing service configuration is stored in .env.js on each host.
"Strictly separate build and run stages."
node build
builds a base12 app, while node run
executes it. node cycle
watches local files and cycles between build and run phases for rapid development.
"Execute the app as one or more stateless processes."
Base12 apps are stateless. The built-in session manager is backed by redis, and apps can be run as any number of independent processes forked from app/index.js. The directory structure provides /tmp for temporary file manipulation, but provides no permanent file storage mechanism since that should be done through a backing service.
"Export services via port binding."
Ultimately, base12 relies on node's built-in http server to field requests. No http container or helper is needed.
"Scale out via the process model."
Using deployment-specific process managers (eg, upstart), base12 keeps the master node.js process running.
In run.js, base12.balance
uses cluster to spawn and monitor multiple processes on a single machine.
New process types can be created by writing modules with a start()
method, and passing that process module to base12.balance()
in run.js.
"Maximize robustness with fast startup and graceful shutdown."
Base12 uses a crash-only design. Uncaught errors exit the process, triggering the balancer to replace it. Startup is nearly immediate.
"Keep development, staging, and production as similar as possible."
We encourage you to keep your .env.js configurations as similar as possible across machines to maximize parity.
"Treat logs as event streams."
Base12 logs events directly to stdout and stderr.
"Run admin/management tasks as one-off processes."
All admin processes are handled with scripts in the /scripts directory. Built-in scripts include provisioning and deployment, tests, dependency management, and generators.
- node.js >= 0.6.x
- npm >= 1.1.x
- redis