docs: function initRoutes (config, route) {
      // create express router for route
      route.router = express.Router({
          caseSensitive: true,
          strict: true,
      })
      // initialize routes depth first so that explicit nested paths come
      // before wildcard paths and are handled correctly by express router
      _.each(route.routes, (subRoute, path) => {
          // get router for sub route
          var router = initRoutes(config, subRoute)
          // bind route for path
          route.router.use('/'+path+'/', router)
      })
      // clear model if no properties are set
      if (_.keys(route.model).length === 0) {
          route.model = undefined
      }
      // clear controller if no properties are set
      if (_.keys(route.controller).length === 0) {
          route.controller = undefined
      }
      // instantiate ImmutableCoreModel
      if (defined(route.model)) {
          route.model = new ImmutableCoreModel(route.model)
          // add model to app register
          config.models[route.model.name] = route.model
      }
      // if model is not set use model for this node
      if (defined(route.controller) && !defined(route.controller.model)) {
          route.controller.model = route.model
      }
      // instantiate ImmutableCoreController - this will create default controllers
      // for model
      var controller = route.controller = new ImmutableCoreController(route.controller)
      // get all templates then remove those that have controllers
      var bareTemplates = _.cloneDeep(route.templates)
      // iterate over paths
      _.each(controller.paths, path => {
          // iterate over http methods for path
          _.each(path, methods => {
              // iterate over handlers for different roles
              _.each(methods, spec => {
                  // role can be specific or default to all
                  var role = spec.role || 'all'
                  // template can be specified or take from method name
                  var template = spec.template || spec.methodName
                  // template name exists locally
                  if (defined(route.templates[template])) {
                      // if there is a template for the controllers role then remove
                      // it from the list of unused templates
                      if (defined(bareTemplates[template].role[role])) {
                          delete bareTemplates[template].role[role]
                      }
                      // otherwise if there is a template for all roles then assign
                      // it to this controller so that another controller for the
                      // all role will not be created to serve the template
                      else if (defined(bareTemplates[template].role['all'])) {
                          delete bareTemplates[template].role['all']
                      }
                  }
              })
          })
      })
      // set to true if any controllers addded
      var added = false
      // create paths for any templates without controllers
      _.each(bareTemplates, (template, templateName) => {
          // iterate over any templates for roles that have not been used
          _.each(template.role, (templatePath, role) => {
              // get path from template name with index becoming /
              var path = templateName === 'index' ? '/' : '/'+templateName
              // create entry for path in controller if not yet defined
              if (!controller.paths[path]) {
                  controller.paths[path] = {}
              }
              // create entry for method if not yet defined
              if (!controller.paths[path]['get']) {
                  controller.paths[path]['get'] = []
              }
              // add spec for template to controller
              controller.paths[path]['get'].push({
                  role: role,
                  template: templatePath,
              })
          })
      })
      // if controllers were added then need to reorder controllers
      if (added) {
          controller.orderControllers()
      }
      // get list of path names
      var pathNames = _.keys(controller.paths)
      // sort path names so that static names go above onces with placeholders
      var sortedPathNames = pathNames.sort(sortPlaceholdersLower)
      // create routes for controller paths
      _.each(sortedPathNames, path => {
          var methods = controller.paths[path]
          // add route for each method
          _.each(methods, (spec, method) => {
              // create ImmutableAppPresenter instance
              var presenter = new ImmutableAppPresenter({
                  config: config,
                  method: method,
                  module: module,
                  path: path,
                  route: route,
                  spec: spec,
              })
              // middleware for route
              var routeMiddleware = []
              // iterate over spec(s) for different roles
              _.each(spec, roleSpec => {
                  // if spec has middleware add to router
                  _.each(roleSpec.middleware, middleware => {
                      routeMiddleware.push(middleware)
                  })
              })
              // add presenter as final middleware
              routeMiddleware.push(presenter)
              // add path to router with method
              route.router[method](path, routeMiddleware)
          })
      })
      // return router so it can be bound to parent
      return route.router
  }