{"_id":"rendr-app-template","_rev":"53-cf151025f51ea9c1e76075a768e5d56e","name":"rendr-app-template","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","dist-tags":{"latest":"0.2.2"},"versions":{"0.0.1":{"name":"rendr-app-template","version":"0.0.1","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","coffee-script":"~1.6.2","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"git+ssh://git@github.com:airbnb/rendr.git#2c9aa6ed8d4f743a066cab2c3c64cfa0ec22e723","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Then, clone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, start the web server. It defaults to port 3030. This will also run `grunt` to compile assets.\n\n    $ npm start\n\n    > rendr-app-template@0.0.1 start /Users/spike/code/rendr-app-template\n\t> DEBUG=app:* node index.js\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"bundle\" task\n\tCompiled /Users/spike/code/rendr-app-template/public/mergedAssets.js\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\n\tDone, without errors.\n\n\tserver pid 71878 listening on port 3030 in development mode\n\nThen pull up the app in your web browser:\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 npm start\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword npm start\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action.  Here is the most simple controller.\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\n\n## Views\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({});\nmodule.exports.id = 'HomeIndexView';\n```\n\nWe set the property `indentifier` on the view constructor to aid in the view hydration process. More on that later.\n\nIf using CoffeeScript, a view constructor's `name` property is set for you.\n\n\n```coffeescript\n# app/views/home_index_view.coffee\nBaseView = require('./base_view')\n\nmodule.exports = class HomeIndexView extends BaseView\n\nconsole.log(module.exports.name)\n => \"HomeIndexView\"\n```\n\n### The view lifecycle\n\n### The view hierarchy\n\n\n## Templates\n\n\n## Asset Bundling\n\n\n## TODO\n* Lazy load repos\n\n## License\n\nMIT\n","_id":"rendr-app-template@0.0.1","dist":{"shasum":"66760e244d1872f1e3e38f571e6c8e50bbc283bb","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.1.tgz","integrity":"sha512-Rh90M0JsLeLFrFfmohE8mkMZI+foND0qa995MzYjVTsIYOOQSwSUIicYkX9CFHrZezdNyFp1BhpcgKejUsvNKw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIECeSrgmUXY93+8gdCGYjMz7kkQGZPE7HD1CHvmL4VWEAiAiFV/+WjWo/qE0Qobdp6RfzqqyEGbsIEc35MctLQsx2w=="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.2":{"name":"rendr-app-template","version":"0.0.2","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","coffee-script":"~1.6.2","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"git+ssh://git@github.com:airbnb/rendr.git#2c9aa6ed8d4f743a066cab2c3c64cfa0ec22e723","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-cli":"~0.1.7","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.2","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `coffee-script` and `grunt-cli` installed globally.\n\n    $ npm install -g coffee-script\n    $ npm install -g grunt-cli\n    \nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ npm install rendr-app-template\n    $ cd rendr-app-template\n\nThen, use `grunt server` to start up the web server and tell Grunt to recompile and restart the server when files change. \n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\t\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\t\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\t\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\t\n\tRunning \"watch\" task\n\tWaiting...\n\nThen pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword npm start\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This is a huge win, because it allows us to just think about application logic when creating our views, models, collections, etc., and not about packaging the modules differently for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\nUsing a trick with the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action.  Here is the most simple controller.\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both  route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view. This is used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above is really doing is specifying a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below.\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  …,\n  \n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app. \n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single \"model\" property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar to Backbone users:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n  \n  events: {\n    'click p': 'handleClick',\n  },\n  \n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `indentifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\n### The view lifecycle\n\n### The view hierarchy\n\n\n## Templates\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","_id":"rendr-app-template@0.0.2","dist":{"shasum":"8e8f2c18770378f9334695e425b4013e50a3f045","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.2.tgz","integrity":"sha512-3ZlH+9TgKnl+jZd/JmBhLXKRr7urrx0HCF8Co2qufyv3LW5NLl+oEMVMPt3Zk9k0C2vdWYt93GRCDso4JdVvIg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGmF6tI0x317vKlY5XBKlYbHgCfuGm24v14yjbiyixeSAiAwZHX5rI0BYAQMRtQ4gNrBgwKMKpjifje4WKCeNWnInw=="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.3":{"name":"rendr-app-template","version":"0.0.3","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","coffee-script":"~1.6.2","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.2.0","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.2","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `coffee-script` and `grunt-cli` installed globally.\n\n    $ npm install -g coffee-script\n    $ npm install -g grunt-cli\n    \nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ npm install rendr-app-template\n    $ cd rendr-app-template\n\nThen, use `grunt server` to start up the web server and tell Grunt to recompile and restart the server when files change. \n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\t\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\t\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\t\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\t\n\tRunning \"watch\" task\n\tWaiting...\n\nThen pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword npm start\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This is a huge win, because it allows us to just think about application logic when creating our views, models, collections, etc., and not about packaging the modules differently for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\nUsing a trick with the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action.  Here is the most simple controller.\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both  route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view. This is used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above is really doing is specifying a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below.\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  …,\n  \n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app. \n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single \"model\" property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar to Backbone users:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n  \n  events: {\n    'click p': 'handleClick',\n  },\n  \n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `indentifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\n### The view lifecycle\n\n### The view hierarchy\n\n\n## Templates\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","_id":"rendr-app-template@0.0.3","dist":{"shasum":"af2ff39a311c704b9e2afe6a2871a0cf8bef0c82","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.3.tgz","integrity":"sha512-vGgIKAygQrcTPbpZMRf04gjYc3iZPpRrAl8Kdlfcpq8qXbVE9Aza1yznhrK0MdcPos4mJVweQLvtjavK7BqeGg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTwLuUsphd/WJahW3FZSSsLTmeD2QAeVs/5D99zxnC+QIgAPX4KXi/XaJOfgtDPo9v/GGeRguDZrZU0kwTu5AKuic="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.4":{"name":"rendr-app-template","version":"0.0.4","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","coffee-script":"~1.6.2","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.2.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.2","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `coffee-script` and `grunt-cli` installed globally.\n\n    $ npm install -g coffee-script\n    $ npm install -g grunt-cli\n    \nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ npm install rendr-app-template\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server and tell Grunt to recompile and restart the server when files change. \n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\t\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\t\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\t\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\t\n\tRunning \"watch\" task\n\tWaiting...\n\nThen pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This is a huge win, because it allows us to just think about application logic when creating our views, models, collections, etc., and not about packaging the modules differently for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\nUsing a trick with the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Now, keep in mind that controllers are executed on both the client and the server. Thus they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is the most simple controller.\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both  route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view. This is used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above is really doing is specifying a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below.\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n  \n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app. \n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n  \n  events: {\n    'click p': 'handleClick',\n  },\n  \n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element. \n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element. \n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n  \n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\t\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\t\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\t\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n  var spec = {\n    model: {model: 'User', params: params}\n  };\n  this.app.fetch(spec, function(err, result) {\n    if (err) return callback(err);\n    // Extend the hash of options we pass to the view's constructor\n    // to include the `template_name` option, which will be used\n    // to look up the template file. This is a convenience so we\n    // don't have to create a separate view class.\n    _.extend(result, {\n      template_name: 'users_show_lazy_view'\n    });\n    callback(err, 'users_show_view', result);\n  });\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","_id":"rendr-app-template@0.0.4","dist":{"shasum":"da1fa0979de26dba50c4a9c091250ac398e4d933","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.4.tgz","integrity":"sha512-mQ6sPc1labVwPwPE0SEghUhnnLfVxFR6rNC1r3Lx75JkJW/h8Ygl6/R3T73ZKFp0xzm9hddOmErlWf3tYQnMdA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDyzI2vfAvu4gxK8k4yTuxtkkQ236EPuqD1tOx4nCN0AAiEAiflCJg+lGAH6wdbdLzAcCiVQ9PG/S0fbgG3y099vilU="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.5":{"name":"rendr-app-template","version":"0.0.5","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","coffee-script":"~1.6.2","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.2.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.2","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `coffee-script` and `grunt-cli` installed globally.\n\n    $ npm install -g coffee-script\n    $ npm install -g grunt-cli\n    \nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ npm install rendr-app-template\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server and tell Grunt to recompile and restart the server when files change. \n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\t\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\t\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\t\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\t\n\tRunning \"watch\" task\n\tWaiting...\n\nThen pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This is a huge win, because it allows us to just think about application logic when creating our views, models, collections, etc., and not about packaging the modules differently for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\nUsing a trick with the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Now, keep in mind that controllers are executed on both the client and the server. Thus they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is the most simple controller.\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both  route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view. This is used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above is really doing is specifying a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below.\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n  \n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app. \n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n  \n  events: {\n    'click p': 'handleClick',\n  },\n  \n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element. \n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element. \n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n  \n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\t\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\t\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\t\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n  var spec = {\n    model: {model: 'User', params: params}\n  };\n  this.app.fetch(spec, function(err, result) {\n    if (err) return callback(err);\n    // Extend the hash of options we pass to the view's constructor\n    // to include the `template_name` option, which will be used\n    // to look up the template file. This is a convenience so we\n    // don't have to create a separate view class.\n    _.extend(result, {\n      template_name: 'users_show_lazy_view'\n    });\n    callback(err, 'users_show_view', result);\n  });\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","_id":"rendr-app-template@0.0.5","dist":{"shasum":"cc472085aa773e8ca88b51ac161dc32b9e33a418","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.5.tgz","integrity":"sha512-dKeVGc/xWYcnZRG39/8Oycz+nUC+9n68O3vp4/v+aBJ5qadW3h8XEI+36n1viOgl7WD+UVmqAWnJnn9Tts9Eng==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCIsC1DLiPWBlAedrKJLWfPWR2gPegXsgQNCPTh871EaAIgeP4PnBlH7sKZSGtB+X6lWRPX4uuNtCNAxtp4rkwCQVs="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.6":{"name":"rendr-app-template","version":"0.0.6","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.2.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.2","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ npm install rendr-app-template\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server and tell Grunt to recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nThen pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This is a huge win, because it allows us to just think about application logic when creating our views, models, collections, etc., and not about packaging the modules differently for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\nUsing a trick with the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Now, keep in mind that controllers are executed on both the client and the server. Thus they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is the most simple controller.\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both  route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view. This is used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above is really doing is specifying a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below.\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n  var spec = {\n    model: {model: 'User', params: params}\n  };\n  this.app.fetch(spec, function(err, result) {\n    if (err) return callback(err);\n    // Extend the hash of options we pass to the view's constructor\n    // to include the `template_name` option, which will be used\n    // to look up the template file. This is a convenience so we\n    // don't have to create a separate view class.\n    _.extend(result, {\n      template_name: 'users_show_lazy_view'\n    });\n    callback(err, 'users_show_view', result);\n  });\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","_id":"rendr-app-template@0.0.6","dist":{"shasum":"d2dac3ae4496f796a1c52cd93034a62a732d9f48","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.6.tgz","integrity":"sha512-4BWvpGKAOwK5w6RFY7yhX++1vRIk1vnTCnSYTooEJOlp9XxQoavJSqe8dxj5mVNUNuf6pDJinEbHea2yAoAQ3g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEyxwmbsw5vcqlnlZuueKksMjQ+apKhQuIi3CfkeWr0cAiEAjldIwyeqM8QpHSy0k2+usC69hrFrTB79BzQ9If+ccXc="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.7":{"name":"rendr-app-template","version":"0.0.7","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.2.4","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.2","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","_id":"rendr-app-template@0.0.7","dist":{"shasum":"2b16d1a4136ac6b8e3e7c833372d4c8cf37ddf45","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.7.tgz","integrity":"sha512-MlULR/5HTyKlSrWg3RBxtYkm24TX7JfrBw52/DjQ1nNPpfnA6Z7rHNveDES/l9cdHH631798UPCYwd6WDQTE7Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDZmSdwq1qynuYr3FRNapScK7cz4Zl+1O+/FCNOyRjaUAiEAoQ/tQ++WI8VrJRaBO1TeLHSvbbaXjr/+h+pegAGFNhM="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.9":{"name":"rendr-app-template","version":"0.0.9","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.3.1","coffee-script":"~1.6.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.4","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","_id":"rendr-app-template@0.0.9","dist":{"shasum":"12d623fc4f2ef03a555b855d6264f01344ca06ec","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.9.tgz","integrity":"sha512-a80/UUjcc2kmlkOHZ0L8R+BsnabtNvJuf/clc7n9hALnzx4m6sv5UWsjw6MqhyoozF3wuT8/SSWnTVZZpPJjPQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICCevgJAzTMRtcj32ayM5u1lIBWJktWUmtfddOt5pFsNAiAEn39g/qXEhx3ZhI6NHAbrrKIXJkC2bOX1Aa1INnU0Lg=="}]},"_from":".","_npmVersion":"1.2.17","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.10":{"name":"rendr-app-template","version":"0.0.10","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.3.3","coffee-script":"~1.6.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.4","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","_id":"rendr-app-template@0.0.10","dist":{"shasum":"ab9ca0bcee6eb4c824456bb2db0d48299aa66866","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.10.tgz","integrity":"sha512-0GNyAg4WMKOr0BdTu/SO4fjrR9VSGqfdRT3+CM2McBZaUSKgVelW9WpLg25P5l5wrDuaZ9igQTVydm7CURdqMA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgl0163vmT7T8/Mw78JhK3gGof4NBqgQdygZqbdwhtWAIhAN+Hz9VKKXJvvWC8XkHGYDODdEaKPOPuZ7e+Sn5yWRvq"}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.11":{"name":"rendr-app-template","version":"0.0.11","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.3.4","coffee-script":"~1.6.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","_id":"rendr-app-template@0.0.11","dist":{"shasum":"fa812805723ae9418bf25742df9ae860c714f10c","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.11.tgz","integrity":"sha512-CYX9K1PwXED061n1S3PlEhJh4F/fS+66AVjsXqzI1wlfqRLh7xb/5b0gcBaFidxuLciFZ8mrZ8R8uK89IpO7Xw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDAdaOlpzHO4ttbanx9Uqxr1kjAaUsUgeB17seccLf2SwIhAMqcRZVPAccx6GBcPl5Mgtui8nTfFPE1NvC9Ja00A8w8"}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.12":{"name":"rendr-app-template","version":"0.0.12","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.3.4","coffee-script":"~1.6.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","_id":"rendr-app-template@0.0.12","dist":{"shasum":"a72e5244d777969f91b9ad49459070b5c4629aad","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.12.tgz","integrity":"sha512-qcqlw42QUOHwJHQyoHFQym50y7eadwQqfkryptRPE8IhxXXOmXFVmTDvXu/uT7XCmBvr3G/FULnyBi5DJ9iMbA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDxU/bspzX7AbQrlxL6b/zsv9+0JFDBrbQJbvI9l+XXKwIhAOsGu8RGc9nHIsMPpmPdQ8qnZFglHymDG3G4PZ0cuWwQ"}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.13":{"name":"rendr-app-template","version":"0.0.13","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.4.0","coffee-script":"~1.6.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","_id":"rendr-app-template@0.0.13","dist":{"shasum":"493e4cdd800b150309310a6acaa267a5f3d8b045","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.13.tgz","integrity":"sha512-xGOpZrF4oyqHc6h9Wwjzi/6GmY5M2pWP3spqc2V/C1Epd1dLidhIGMdHRTOR818q3YecptLh58LSAVPnQJc7gA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCrnnyz2p1fx1CqfV2BRxIURG5FeiMj3wdrBhbPsT95dwIhAPDsezf4Ff5bO3N9c90vDnVUqaqDfrHi/kDQRPkXgReh"}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.14":{"name":"rendr-app-template","version":"0.0.14","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.4.3","coffee-script":"~1.6.2","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","_id":"rendr-app-template@0.0.14","dist":{"shasum":"d73a287c99218e85646ab6076f021f6f1b391f33","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.14.tgz","integrity":"sha512-EnqVeHjBOUyPRkPDrTD81r5UIjHtKU7a8NKbmcnQjoyEIw91Rtjey68TWr/S24h4+MKYrDxLK+YAuAefvDBrmw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICGikoR6nUzR4yGI+SL2We8VHEUPvnfw1x8hFyR7EJ77AiAvhTY3atOJPeSf0+gXZT823P5D19cXDbKOi4wOLPnEUA=="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.15":{"name":"rendr-app-template","version":"0.0.15","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.4.4-rc.3","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#d61e7457c6551965f88de46ad207fd67d18ddd4a","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","_id":"rendr-app-template@0.0.15","dist":{"shasum":"091edb773421c5b304c044522cfc3063a6cc705b","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.15.tgz","integrity":"sha512-2gqrl+iE0p/etQU1ljmscsz7piFlRe9dcn9tDy0nVZgiWuEBL4j3u6OqTM+hYvxKBEeaven0r4D+XIvhVL3X2Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxBsR1LzGmmVZ6s45zzxrcJgVD1nQAwKP8IFV5cyqywgIgExXsnW9NleZ/LKfIew5JJq+Z4+D9UlF/pdeic36+ooc="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.16":{"name":"rendr-app-template","version":"0.0.16","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"~0.4.4-rc.3","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#0395c6fa9c765616af34cafad377572196068cf8","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","_id":"rendr-app-template@0.0.16","dist":{"shasum":"d79daaa00d49b970890684a32d8e3fcb6c1651f9","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.16.tgz","integrity":"sha512-aNIRuAjQ2GtalcUgTeBkdw3s5b2tYTaAdIybPfNeBiQzKmPpxuHvR5TRQn7MIpfhuDDVlAyMz9jht/Bf1GmZJg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNJEIVeMtHLXyvQOXgIzHxR4SPb+HqH1BJfcnmCR/icQIhAMyJ5RAcfpfEU0RK1+p7Poq4CzrkFGbhxKyknKSDaG8v"}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.17":{"name":"rendr-app-template","version":"0.0.17","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"0.4.6-rc.1","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#0395c6fa9c765616af34cafad377572196068cf8","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a sublcass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBe default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/airbnb/rendr-app-template/issues"},"_id":"rendr-app-template@0.0.17","dist":{"shasum":"529057b81aeac1fc6c7f2e07d59d305afcf7c6e2","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.17.tgz","integrity":"sha512-G3Hg4SYnVZIjJrPVOkDfpdtS/2NejHg2JPDFtdRBLyiqEr9Bj3yEYmWkmRBNZ7kIAKZAAbZJyW5k3BOVTdNUaw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBtLFwGVjOq6CelI4UldBQwyY0t0pwbTe49nEh0pt8GOAiEApOyQ9apirakqYlol8EBR8EsHb7odD7DhOdomnvUSNf0="}]},"_from":".","_npmVersion":"1.2.21","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.0.19":{"name":"rendr-app-template","version":"0.0.19","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr":"0.4.7-rc.3","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#0395c6fa9c765616af34cafad377572196068cf8","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a subclass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBy default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/airbnb/rendr-app-template/issues"},"_id":"rendr-app-template@0.0.19","dist":{"shasum":"78fa43e81817c3850b3729b7b1d04bc9c455fdc5","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.0.19.tgz","integrity":"sha512-USJAUf9ombHj2RhP7hf0iaj7JxSNEDahJS0hvRoFYmR6YzUHEUuFnVeItB++laehH90jEpQH6LHmmVRq5h7VaQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE4yQds7yTZn2UgS8GOb77lUBUEXeb2uw+QX5mDfU6cbAiEAwwI9SAKZhqXcqO3OykXK/+cjtFzTtmW6RIPBcTdaK6E="}]},"_from":".","_npmVersion":"1.2.21","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.1.0":{"name":"rendr-app-template","version":"0.1.0","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr-handlebars":"0.0.2","rendr":"0.4.8-alpha.01","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#0395c6fa9c765616af34cafad377572196068cf8","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a subclass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `identifier` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBy default, `getTemplateName()` returns the underscored version of the view constructor's `identifier` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/airbnb/rendr-app-template/issues"},"_id":"rendr-app-template@0.1.0","dist":{"shasum":"7b35f8db5b0acf9c81b39fa2129d63562f2424a0","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.1.0.tgz","integrity":"sha512-IFbovcOUr6/1uba9QKBl9DjxoLkCULQDL/u2lovzhxyXAAKTQrxxzIPh3+t8Wd6DCE9fXqXgPmoBLCnHVMpECw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDY0GysrR+u8cn5g9DwY+miUmzz4d3575ihL4tGgNE5xAiEAzLbNdlFG8iRofdpIN1whUHm7OMXXzt/Zj7mS3/24eHU="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.1.4":{"name":"rendr-app-template","version":"0.1.4","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr-handlebars":"0.0.5","rendr":">=0.4.8-4","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#3c12d01dca9c4b9e871f40dab040420b3a72a3f7","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a subclass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `id` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBy default, `getTemplateName()` returns the underscored version of the view constructor's `id` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/airbnb/rendr-app-template/issues"},"_id":"rendr-app-template@0.1.4","dist":{"shasum":"efec82cd68c039ade25ae9f3d86a19cdf08f14b8","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.1.4.tgz","integrity":"sha512-WfLtvzT1g7Nz30iZLImiMNYDkwXTYAvTYABahlSVW/ESyvNzFEnZzZBh95wnkXpz6u5fh9KFPjSbj2icdttiSw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDmL5wSrek/42G7N0QgrZOOeo17HU5u5D7WzbRZ9Cb8rgIhAMOp9pLWMApVQmrbhk+7cqoql/WwgNpYaQmCGAVN+7iv"}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.1.5":{"name":"rendr-app-template","version":"0.1.5","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr-handlebars":"0.0.5","rendr":">=0.4.8-4","debug":"*"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#a4ae75750efeb23bf8ca9c61d9cf7569d40879fa","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","grunt-bg-shell":"~2.0.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a subclass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `id` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBy default, `getTemplateName()` returns the underscored version of the view constructor's `id` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users_show_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_show_view.hbs) and [`app/views/users_show_view.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users_show_view.js) for an example:\n\n```html\n<!-- app/templates/users_show_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users_show_view` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users_show_view`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users_show_view` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users_show_lazy_view'\n      });\n      callback(err, 'users_show_view', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users_show_lazy_view` template, abbreviated:\n\n```html\n<!-- app/templates/users_show_lazy_view.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users_show_view` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/airbnb/rendr-app-template/issues"},"_id":"rendr-app-template@0.1.5","dist":{"shasum":"a90f4778b8b03b323cb02915c82128e308e3570f","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.1.5.tgz","integrity":"sha512-2qErYWftjp8dQA44nSZ5FNNEfLmo89RhH9+bozbdZ2SNNHsy+X7rFaAFFnr4a8GvKCtmbOnpcGZgA7ST+vFLoA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFkWR3+no7aCwIP7C0UFasgkwC7CTR4wXZPyIShySpXAAiAiwrJHe0Xw/Bm/LylR74NGRwKco9GK6lNd6bFLqSoYUQ=="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.2.0":{"name":"rendr-app-template","version":"0.2.0","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr-handlebars":"0.0.5","rendr":"0.5.0-alpha04","debug":"*","config":"0.4.x","js-yaml":"2.x.x"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#a4ae75750efeb23bf8ca9c61d9cf7569d40879fa","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a subclass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `id` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBy default, `getTemplateName()` returns the underscored version of the view constructor's `id` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users/show.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users/show.hbs) and [`app/views/users/show.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users/show.js) for an example:\n\n```html\n<!-- app/templates/users/show.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users/show` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users/show`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users/show` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users/show_lazy'\n      });\n      callback(err, 'users/show', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users/show_lazy` template, abbreviated:\n\n```html\n<!-- app/templates/users/show_lazy.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users/show` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/airbnb/rendr-app-template/issues"},"_id":"rendr-app-template@0.2.0","dist":{"shasum":"1fa99f2cc8e1c5ebc0511acc950fc4ef8357ef2f","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.2.0.tgz","integrity":"sha512-YgHKRrHE1XXzD8NfKSB/lCL26postNhx2Jt4NOixoE6Qc2dklaziDeGApmH4p1SMaGxFTOo3L4hk5rKdPDEbuA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEj9oJ09nqfkPyS49USWmpYzU1Iz0PMgem1KmD/0kFU6AiEA7ZO/rhnv5JfrMUWlijalFq+aD0PT7JyRvwsgBdFGFrs="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"directories":{}},"0.2.1":{"name":"rendr-app-template","version":"0.2.1","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr-handlebars":"0.0.5","rendr":"0.5.0-alpha04","debug":"*","config":"0.4.x","js-yaml":"2.x.x"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#a4ae75750efeb23bf8ca9c61d9cf7569d40879fa","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a subclass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `id` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBy default, `getTemplateName()` returns the underscored version of the view constructor's `id` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users/show.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users/show.hbs) and [`app/views/users/show.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users/show.js) for an example:\n\n```html\n<!-- app/templates/users/show.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users/show` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users/show`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users/show` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users/show_lazy'\n      });\n      callback(err, 'users/show', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users/show_lazy` template, abbreviated:\n\n```html\n<!-- app/templates/users/show_lazy.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users/show` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/airbnb/rendr-app-template/issues"},"_id":"rendr-app-template@0.2.1","dist":{"shasum":"d5d2c7cd6cfc6321d776644ba692933f30557fea","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.2.1.tgz","integrity":"sha512-CskpAsyjPbyxSRZZG9MlOOais/Z0uJB1sj05WwQyOjBfsL978T/tJNwyFHCUc2tRkDY1RLVnlj4Wgc2xOnfx4w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHEdXgTxMG2iK1NwxWKUMy1HXJA6U573l5/O8Uff901UAiEAksiYvkS8Yr8MSG3DAdUdsJ+jBythwIDydyadnU/KuVc="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}]},"0.2.2":{"name":"rendr-app-template","version":"0.2.2","description":"The purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.","main":"index.js","scripts":{"test":"mocha --ui bdd --reporter spec  ./test --recursive","start":"DEBUG=app:* node index.js"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"},"dependencies":{"express":"~>3","underscore":"~1.4.4","async":"~0.1.22","request":"~2.16","rendr-handlebars":"0.0.5","rendr":"0.5.0-alpha07","debug":"*","config":"0.4.x","js-yaml":"2.x.x"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-stylus":"~0.5.0","grunt-contrib-handlebars":"git://github.com/spikebrehm/grunt-contrib-handlebars#a4ae75750efeb23bf8ca9c61d9cf7569d40879fa","grunt-rendr-stitch":"~0.0.6","grunt-contrib-watch":"~0.3.1","nodemon":"~0.7.6","mocha":"~1.9.0","should":"~1.2.2"},"engines":{"node":">=0.8"},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n![Screenshot](http://cl.ly/image/062d3S2D1Y38/Screen%20Shot%202013-04-09%20at%203.14.31%20PM.png)\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Also, make sure to have `grunt-cli` installed globally.\n\n    $ npm install -g grunt-cli\n\nIf you see an error on startup that looks [like this](https://github.com/airbnb/rendr-app-template/issues/2), then you may need to un-install a global copy of `grunt`:\n\n    $ npm uninstall -g grunt\n\nClone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, use `grunt server` to start up the web server. Grunt will recompile and restart the server when files change.\n\n    $ grunt server\n\tRunning \"bgShell:runNode\" (bgShell) task\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"rendr_stitch:compile\" (rendr_stitch) task\n\t4 Apr 09:58:02 - [nodemon] v0.7.2\n\t4 Apr 09:58:02 - [nodemon] watching: /Users/spike1/code/rendr-app-template\n\t4 Apr 09:58:02 - [nodemon] starting `node index.js`\n\t4 Apr 09:58:02 - [nodemon] reading ignore list\n\tFile \"public/mergedAssets.js\" created.\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\tserver pid 87338 listening on port 3030 in development mode\n\n\tRunning \"watch\" task\n\tWaiting...\n\nNow, pull up the app in your web browser. It defaults to port `3030`.\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 grunt server\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword grunt server\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nIt's worthwhile to read the first [blog post](http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product), which has some background on Rendr and its *raison d'être*.\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## CommonJS using Stitch\n\nNode.js uses the CommonJS module pattern, and using a tool called [Stitch](https://github.com/sstephenson/stitch), we can emulate it in the browser. This looks familiar in Node.js:\n\n```js\nvar User = require('app/models/user');\n```\nUsing Stitch, we can use the same `require()` function in the browser. This allows us to focus on application logic, not packaging modules separately for client and server.\n\nIn Node.js, you can also use `require()` to load submodules within NPM models. For example, we could load Rendr's base view in order to extend it to create a view for our app.\n\n```js\nvar BaseView = require('rendr/shared/base/view');\n```\n\nBecause of a trick in the way we do Stitch packaging, this module path works in the browser as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action. Keep in mind that controllers are executed on both the client and the server. Thus, they are an abstraction whose sole responsibility is to specify which data is needed to render the view, and which view to render.\n\nOn the server, controllers are executed in response to a request to the Express server, and are used to render the initial page of HTML. On the client, controllers are executed in response to `pushState` events as the user navigates the app.\n\nHere is a very simple controller:\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\nEvery action gets called with two arguments: `params` and `callback`. The `params` object contains both route params and query string params. `callback` is called to kick off view rendering. It has this signature:\n\n```js\nfunction(err, viewName, viewData) {}\n```\n\n### `err`\nFollowing the Node.js convention, the first argument to the callback is `err`. We'll pass null here because we're not fetching any data, but if we were, that's how we'd communicate a fetching error.\n\n### `viewName`\nThis is a string identifier of a view, used by the router to find the view class, i.e.:\n\n```js\nrequire('app/views/' + viewName);\n```\n\n### `viewData` (optional)\nAn object to pass to the view constructor. This is how we pass data to the view.\n\nAll our `index` action above really does is specify a view class. This is the simple case -- no data fetching, just synchronous view rendering.\n\nIt gets more interesting when we decide to fetch some data. Check out the `repos_controller` below:\n\n```js\n// app/controllers/repos_controller.js\nmodule.exports = {\n  // ...\n\n  show: function(params, callback) {\n    var spec = {\n      model: {model: 'Repo', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      callback(err, 'repos_show_view', result);\n    });\n  }\n};\n\n```\n\nYou see here that we call `this.app.fetch()` to fetch our Repo model. Our controller actions are executed in the context of the router, so we have a few properties and methods available, one of which is `this.app`. This is the instance of our application's App context, which is a sublcass of `rendr/base/app`, which itself is a subclass of `Backbone.Model`. You'll see that we inject `app` into every model, view, collection, and controller; this is how we maintain app context throughout our app.\n\nYou see here that we call `callback` with the `err` that comes from `this.app.fetch()`, the view class name, and the `result` of the fetch. `result` in this case is an object with a single `model` property, which is our instance of the `Repo` model.\n\n`this.app.fetch()` does a few nice things for us; it fetches models or collections in parallel, handles errors, does caching, and most importantly, provides a way to boostrap the data fetched on the server in a way that is accessible by the client-side on first render.\n\n## Views\n\nA Rendr view is a subclass of `Backbone.View` with some additional methods added to support client-server rendering, plus methods that make it easier to manage the view lifecycle.\n\nCreating your own view should look familiar if you've used Backbone:\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  events: {\n    'click p': 'handleClick',\n  },\n\n  handleClick: function() {…}\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nYou can add `className`, `tagName`, `events`, and all of the other `Backbone.View` properties you know and love.\n\nWe set the property `id` on the view constructor to aid in the view hydration process. More on that later.\n\nOur views, just like all of the code in the `app/` directory, are executed in both the client and the server, but of course certain behaviors are only relevant in the client. The `events` hash is ignored by the server, as well as any DOM-related event handlers.\n\nNotice there's no `render()` method or `template` property specified in the view. The philosophy here is that sensible defaults and convention over configuration should allow you to skip all the typical boilerplate when creating views. The `render()` method should be the same for all your views; all it does is  mash up the template with some data to generate HTML, and insert that HTML into the DOM element.\n\nNow, because we're not using a DOM to render our views, we must make sure that the view returns all its HTML as a string. On the server, `view.getHtml()` is called, which returns the view's outer HTML, including wrapper element. This is then handed to Express, which wraps the page with a layout and sends the full HTML page to the client. Behind the scenes, `view.getHtml()` calls `view.getInnerHtml()` for the inner HTML of the view, not including wrapping element, and then constructs the wrapping element based on the `tagName`, `className`, etc. properties, and the key-value pairs of HTML attributes returned by `view.getAttributes()`, which allows you to pass custom attributes to the outer element.\n\nOn the client, `view.render()` is called, which updates the view's DOM element with the HTML returned from `view.getInnerHtml()`. By default, Backbone will create the wrapper DOM element on its own. We make sure to also set any custom HTML attributes in `view.getAttributes()` on the element.\n\n### The view lifecycle\n\n\nA common need is to run some initialization code that touches the DOM after render, for things like jQuery sliders, special event handling, etc. Rather than overriding the `render()` method, use `postRender()`. The `postRender()` method is executed for every view once after rending, including after initial pageload.\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({\n  className: 'home_index_view',\n\n  postRender: function() {\n    this.$('.slider').slider();\n  }\n});\nmodule.exports.id = 'HomeIndexView';\n```\n\nIf you have a need to customize the way your views generate HTML, there are a few specific methods you can override.\n\n#### getTemplateName()\n\nBy default, `getTemplateName()` returns the underscored version of the view constructor's `id` property; so in our case, `home_index_view`. It will also look for `options.template_name`, which is useful for initialing views to use a certain template. The view will look in `app/templates` for the value returned by this function.\n\n#### getTemplate()\n\nIf `getTemplateName()` isn't enough, you can override `getTemplate()` to return a function that takes a single `data` argument and returns HTML:\n\n```js\nfunction(data) {\n  ...\n  return html;\n}\n```\n\nThis HTML is used to populate the view's inner HTML; that is, not including the wrapper element, which you can specify on the view itself using `tagName`, `className`, and `id`.\n\n#### getInnerHtml()\n\nIf you're building some sort of composite view that doesn't utilize a simple template, override `getInnerHtml()`. This is useful for tabbed views, collection views, etc.\n\n#### getHtml()\n\nYou probably shouldn't ever need to override this; by default it just combines the HTML returned by `getInnerHtml()` and the HTML attributes returned by `getAttributes()` to produce an outer HTML string.\n\n## The view hierarchy\n\nRendr provides a Handlebars helper `{{view}}` that allows you to declaratively nest your views, creating a view hierarchy that you can traverse in your JavaScript.  Check out [`app/templates/users/show.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users/show.hbs) and [`app/views/users/show.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/views/users/show.js) for an example:\n\n```html\n<!-- app/templates/users/show.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection=repos}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nYou see that we use the `{{view}}` helper with an argument that indicates which view to be rendered. We can pass data into the view using [Handlebars' hash arguments](http://handlebarsjs.com/expressions.html). Anything you pass as hash arguments will be pass to the subview's constructor and be accessible as `this.options` within the subview. There are a few special options you can pass to a view: `model` or `collection` can be used to directly pass a model or collection instance to a subview. The options `model_name` + `model_id` or `collection_name` + `collection_params` can be used in conjunction with `lazy=\"true\"` to lazily fetch models or collections; more on that later.\n\nNow, from within the `users/show` view, we can access any child views using the `this.childViews` array.  A good way to debug and get a feel for this in the browser is to drill down into the global `App` property, which is your instance of `BaseApp`. From `App` you can access other parts of your application. `App.router` is your instance of `ClientRouter`, and it has a number of properties that you can inspect. One of these is `App.router.currentView`, which will always point to the current main view for a page.  For example, if you are viewing wycats' page in our app, [http://localhost:3030/users/wycats](http://localhost:3030/users/wycats), `currentView` will be an instance of `users/show`:\n\n    App.router.currentView\n    => child {render: function, cid: \"view434\", model: child, options: Object, $el: p.fn.p.init[1]…}\n\nFrom there, we can find our child `user_repos_view` view:\n\n\tApp.router.currentView.childViews\n\t=> [child]\n\n\tApp.router.currentView.childViews[0]\n\t=> child {render: function, cid: \"view436\", options: Object, $el: p.fn.p.init[1], el: div.user_repos_view…}\n\nCheck out its collection property, which is the instance of `Repos` which we fetched in the controller and passed down in the `{{view}}` helper:\n\n\tApp.router.currentView.childViews[0].collection\n\t=> child {options: Object, app: child, params: Object, meta: Object, length: 30…}\n\nYou can nest subviews *ad infinitum*. Our `user_repos_view` has an empty `childViews` array now, but we could add some subviews if we found it useful for organizing our codebase, or keeping things DRY.\n\n\tApp.router.currentView.childViews[0].childViews\n\t=> []\n\nViews also have a `parentView` property, which will be non-null unless they are a top-level view.\n\n\tApp.router.currentView.childViews[0].parentView === App.router.currentView\n\t=> true\n\n\tApp.router.currentView.parentView\n\t=> null\n\n## Lazy-loading data for views\n\nSo far, our [`users#show` action](https://github.com/airbnb/rendr-app-template/blob/master/app/controllers/users_controller.js#L11) pulls down both a `User` model and a `Repos` collection for that model. If we were to navigate from `users#index` to `users#show`, we already have that user model cached in memory (because we fetched it in order to render the list), but we have to make a roundtrip to the server to fetch the `Repos`, which aren't part of the `User` attributes. This means that instead of immediately rendering the `users/show` view, we wait for the `Repos` API call to finish. But what if instead we want to lazy-load the `Repos` so we can render that view immediately for a better user experience?\n\nWe can achieve this by lazy-loading models or collections in our subviews. Check out the `users#show_lazy` action, which demonstrates this approach:\n\n```js\n// app/controllers/users_controller.js\nmodule.exports = {\n  // ...\n\n  show_lazy: function(params, callback) {\n    var spec = {\n      model: {model: 'User', params: params}\n    };\n    this.app.fetch(spec, function(err, result) {\n      if (err) return callback(err);\n      // Extend the hash of options we pass to the view's constructor\n      // to include the `template_name` option, which will be used\n      // to look up the template file. This is a convenience so we\n      // don't have to create a separate view class.\n      _.extend(result, {\n        template_name: 'users/show_lazy'\n      });\n      callback(err, 'users/show', result);\n    });\n  }\n}\n```\nThe first thing to notice is that in our fetch `spec`, we only specify the `User` model, leaving out the `Repos` collection. Then, we tell the view to use a different template than the default. We do this by passing in a `template_name` property to the view's options, which is passed to its constructor. We extend the `result` object to have this; the third argument to our `callback` is an object that's passed to the view's constructor. We could have also created a separate view class in JavaScript for this, to match our new template.\n\nHere's the `users/show_lazy` template, abbreviated:\n\n```html\n<!-- app/templates/users/show_lazy.hbs -->\n...\n\n<div class=\"span6\">\n  {{view \"user_repos_view\" collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"}}\n</div>\n\n<div class=\"span6\">\n  ...\n</div>\n```\n\nSo, the only difference to our original `users/show` template is that instead of passing `collection=repos` to our `user_repos_view` subview, we pass `collection_name=\"Repos\" param_name=\"login\" param_value=login lazy=\"true\"`. When fetching collections, we specify params, which are used to fetch and cache the models for that collection. We quote all of these arguments except for `param_value=login`; quoted arguments are passed in as string literals, and unquoted arguments are references to variables that are available in the current Handlebars scope. `login` is one of the attributes of a `User` model, which gets passed into the template. The `lazy=\"true\"` tells the view that it needs to fetch (or find a cached version of) the specified model or collection.\n\nWe can see this at play in our app if we add a route in our [`app/routes.js`](https://github.com/airbnb/rendr-app-template/blob/master/app/routes.js#L7) file that routes `users_lazy/:login` to `users#show_lazy`, and change our [`app/templates/users_index_view.hbs`](https://github.com/airbnb/rendr-app-template/blob/master/app/templates/users_index_view.hbs#L6) to link to `/users_lazy/{{login}}`.\n\nNow, if we click from the list of users on `users#index`, you'll see the page gets rendered immediately, and the repos are rendered once the API call finishes. If you click back and forward in your browser, you see it's cached.\n\n## Templates\n\nSo far, Rendr just supports Handlebars templates, but it should be possible to make this interchangeable. For now, place your templates in `app/templates` with a name that matches the underscorized view's identifier and file extension of `.hbs`.  So, the view with an identifier of `HomeIndexView` will look for a template at `app/templates/home_index_view.hbs`.\n\n\n## Interacting with a RESTful API\n\n\n## Assets\n\nIn this example we use [Grunt](https://github.com/gruntjs/grunt) to manage asset compilation. We compile JavaScripts using [Stitch](https://github.com/sstephenson/stitch) and stylesheets using [Stylus](https://github.com/learnboost/stylus). Check out `Gruntfile.js` in the root directory of this repo for details.\n\n\n## License\n\nMIT\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/airbnb/rendr-app-template/issues"},"_id":"rendr-app-template@0.2.2","dist":{"shasum":"a2d0ba9c74009565f923c568cc30a2f22944b7e1","tarball":"https://registry.npmjs.org/rendr-app-template/-/rendr-app-template-0.2.2.tgz","integrity":"sha512-BKpOX+/aOH1cT2hiBPlFlb06gzr5NOGc3o7jz6Cbb/QfK/5cSTWhHPA7VyVjLuUn6W6AE96owUBewEhgkmIsRw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDheOe0DfOW/9qtzV1VrH4IYJQYZCLl3kQnxdixR+75EQIhAJ94xBrKQ9l75qdLvkKWPcs1g6QmLfm7sz0l/nHXUeyC"}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"spikebrehm","email":"ocelot@gmail.com"},"maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}]}},"readme":"# Rendr App Template\n## GitHub Browser\n\nThe purpose of this little app is to demonstrate one way of using Rendr to build a web app that runs on both the client and the server.\n\n## Running the example\n\nFirst, make sure to have Node >= 0.8.0 [installed on your system](http://nodejs.org/). Then, clone this repo to a local directory and run `npm install` to install dependencies:\n\n    $ git clone git@github.com:airbnb/rendr-app-template.git\n    $ cd rendr-app-template\n    $ npm install\n\nThen, start the web server. It defaults to port 3030. This will also run `grunt` to compile assets.\n\n    $ npm start\n\n    > rendr-app-template@0.0.1 start /Users/spike/code/rendr-app-template\n\t> DEBUG=app:* node index.js\n\n\tRunning \"handlebars:compile\" (handlebars) task\n\tFile \"app/templates/compiledTemplates.js\" created.\n\n\tRunning \"bundle\" task\n\tCompiled /Users/spike/code/rendr-app-template/public/mergedAssets.js\n\n\tRunning \"stylus:compile\" (stylus) task\n\tFile public/styles.css created.\n\n\tDone, without errors.\n\n\tserver pid 71878 listening on port 3030 in development mode\n\nThen pull up the app in your web browser:\n\n    $ open http://localhost:3030\n\nYou can choose a different port by passing the `PORT` environment variable:\n\n    $ PORT=80 npm start\n\n### GitHub API rate limit\n\nGitHub [rate limits](http://developer.github.com/v3/#rate-limiting) unauthenticated requests to its public API to 60 requests per hour per IP. This should be enough for just playing with the sample app, but if you pull it down and start developing off it you may run up against the rate limit.\n\nIf this happens to you, you can supply your GitHub creds for HTTP Basic Auth using the BASIC_AUTH environment variable. **Be very, very careful with this!** It means you will be typing your GitHub credentials in plain text, which will be saved to your Bash history and may be intercepted by other programs. If you do this, immediately change your password before and afterwards. This should only be necessary if you're developing on the app and need to keep refreshing the page.\n\n\t$ BASIC_AUTH=githubusername:githubpassword npm start\n\n**You've been warned.** Your best bet may be to alter the project to read from your favorite RESTful API.\n\n## Getting Started With Rendr\n\nThis basic Rendr app looks like a hybrid between a standard client-side MVC Backbone.js app and an Express app, with a little Rails convention thrown in.\n\nCheck out the directory structure:\n\n    |- app/\n    |--- collections/\n    |--- controllers/\n    |--- models/\n    |--- templates/\n    |--- views/\n    |--- app.js\n    |--- router.js\n    |--- routes.js\n    |- assets/\n    |- config/\n    |- public/\n    |- server/\n\n**Note**: I want to stress that this is just one way to build an app using Rendr. I hope it can evolve to support a number of different app configurations, with the shared premise that the components should be able to run on either side of the wire. For example, the full-on client-side MVC model isn't appropriate for all types of apps. Sometimes it's more appropriate to load HTML fragments over the wire, also known as PJAX. Rendr apps should be able to support this as well.\n\n## Routes file\n\n```js\n// app/routes.js\nmodule.exports = function(match) {\n  match('',                   'home#index');\n  match('repos',              'repos#index');\n  match('repos/:owner/:name', 'repos#show');\n  match('users'       ,       'users#index');\n  match('users/:login',       'users#show');\n};\n\n```\n\n## Controllers\n\nA controller is a simple JavaScript object, where each property is a controller action.  Here is the most simple controller.\n\n```js\n// app/controllers/home_controller.js\nmodule.exports = {\n  index: function(params, callback) {\n    callback(null, 'home_index_view');\n  }\n};\n\n```\n\n\n## Views\n\n```js\n// app/views/home_index_view.js\nvar BaseView = require('./base_view');\n\nmodule.exports = BaseView.extend({});\nmodule.exports.id = 'HomeIndexView';\n```\n\nWe set the property `indentifier` on the view constructor to aid in the view hydration process. More on that later.\n\nIf using CoffeeScript, a view constructor's `name` property is set for you.\n\n\n```coffeescript\n# app/views/home_index_view.coffee\nBaseView = require('./base_view')\n\nmodule.exports = class HomeIndexView extends BaseView\n\nconsole.log(module.exports.name)\n => \"HomeIndexView\"\n```\n\n### The view lifecycle\n\n### The view hierarchy\n\n\n## Templates\n\n\n## Asset Bundling\n\n\n## TODO\n* Lazy load repos\n\n## License\n\nMIT\n","maintainers":[{"name":"spikebrehm","email":"ocelot@gmail.com"}],"time":{"modified":"2022-06-26T11:15:25.506Z","created":"2013-04-01T07:21:21.293Z","0.0.1":"2013-04-01T07:21:22.013Z","0.0.2":"2013-04-04T17:01:03.914Z","0.0.3":"2013-04-05T20:39:42.780Z","0.0.4":"2013-04-09T23:42:22.274Z","0.0.5":"2013-04-09T23:51:30.516Z","0.0.6":"2013-04-10T00:33:30.246Z","0.0.7":"2013-04-18T17:45:28.937Z","0.0.9":"2013-04-24T21:39:59.560Z","0.0.10":"2013-04-25T19:05:19.236Z","0.0.11":"2013-04-26T01:45:06.901Z","0.0.12":"2013-04-27T21:27:16.280Z","0.0.13":"2013-04-29T17:19:26.399Z","0.0.14":"2013-05-01T00:58:45.463Z","0.0.15":"2013-05-03T06:33:00.737Z","0.0.16":"2013-05-15T21:17:53.032Z","0.0.17":"2013-06-02T19:00:29.843Z","0.0.19":"2013-06-18T15:30:52.157Z","0.1.0":"2013-06-29T02:14:25.666Z","0.1.4":"2013-07-14T22:13:17.929Z","0.1.5":"2013-07-15T03:36:25.149Z","0.2.0":"2013-09-26T21:27:48.351Z","0.2.1":"2013-09-27T02:26:42.711Z","0.2.2":"2013-10-17T03:54:17.734Z"},"repository":{"type":"git","url":"git://github.com/airbnb/rendr-app-template.git"}}