diretto

Filesystem-based routing for Express.js

Diretto

A file-based router for Express / Connect

Diretto makes it easy to create content folders (can be named anything) to easily serve content with granular control of application behaviour. It's inspired by files-based CMSs like Stacey, but it uses Node.js and Express.js.

Create a folder in your project, anywhere (project root in this example):

  • /appDir
    • /projects
      • /project-1
        • /public
          • style.less
        • index.jade
        • index.yml
      • /some-other-project
        • /public
          • style.less
        • index.jade
        • index.yml
      • /...

The YML may look like this (url is required):

url: some-cool-project
title: The Project Title
description: This is a description for Google
author: Tommaso <tom@lnz.com>
date:
  modified: 2013-03-13
  published: 2013-02-23
published: true
var lessMW  = require('less-middleware');
var path    = require('path');
var express = require('express');
 
var app = express();
 
app.get('/', function(reqres){
  res.send('hello world');
});
app.listen(3000); 
 
 
// Require Diretto 
var diretto = require('./connect-diretto');
 
// Create a new instance pointing to the projects folder 
// You can require() and call diretto() as much as you need. 
// Once initialised, calls to diretto(dataDir) will simply 
// return a reference if the dataDir is the same as a previous one. 
var projects = diretto(__dirname + '/projects');
 
// Mount the middleware 
// Note we mount the middleware to respond on /work (this could be 
// anything or left empty). Watch out for middleware stack order! 
app.use("/work", projects.get('middleware'));
 
// Use `mount()` instead of `app.use()` here if you also want to use `watch()` 
// projects.mount(app, '/work'); 
// projects.watch(); 
// projects.on('update', function() { 
//   projects.each(function(config, subapp) { 
//      // do your thing here…  
//   });    
// }) 
 
 
// Set it up 
projects.each(function(configsubapp) {
    var cfg = subapp.get('config');
    subapp.set('views', path.join(cfg.dirname, cfg.filename));
    subapp.set('view engine', 'jade');
    subapp.use(lessMW({ src: path.join(cfg.dirname, cfg.filename, '/public') }));
    subapp.use(express.static(path.join(cfg.dirname, cfg.filename, '/public')));
    subapp.use(subapp.router);
 
    subapp.get('/', function (reqres) {
        res.render("index", cfg);
    });
});
---
url: some-cool-project
title: The Project Title
description: This is a description for Google
author: Tommaso <tom@lnz.com>
date:
  modified: 2013-03-13
  published: 2013-02-23
published: true
---
some: extra
document: here
---
and: so
on: ...
h1= title
~ node app.js
    -> express running to on port 3000

Visit localhost:3000/work/some-cool-project/

If it had a face he would look like this:

{
    // Instance of Config. See below. 
    'cool-project-url': {
        'url': 'cool-project-url',
        'title': 'My Project Title',
        '...'
        'docs': [
            { 'some-other-stuff': 'found in the YAML after the second --- doc separator' },
            { 'my-long-markdown-essay': 'Markdown **ensues**…' }
        ]
    },
    // Instance of Config. See below. 
    'another-cool-project': {
        'url': 'cool-project-url',
        '...',
        'docs': []
    }
}

Each Diretto instance provides the following methods:

diretto.each(function(config, app) {…})

Iterates over each config and app via an iterator function.

diretto.update(_[function(config, app) {…}]_)

Re-reads the root diretory and updates all configs. Changes are logged in the console.

diretto.init()

Use to initialise the instance and by update()

diretto.watch()

(TODO)

Diretto fires the following events:

diretto.on('update', fn)

Fires when the configurations are loaded and the instance is ready to be used