diff --git a/docs/v1/examples/auth.md b/docs/v1/examples/auth.md
index a4e7694..26e1848 100644
--- a/docs/v1/examples/auth.md
+++ b/docs/v1/examples/auth.md
@@ -7,6 +7,17 @@ provider and the [$goUsers](../users.md) service.
The full source for this example can be found [here](https://github.com/colinmacdonald/goangular-auth-example).
+## Table of Contents
+
+1. [Install](#1.-install)
+2. [Set up view](#2.-set-up-view)
+3. [Configure GoAngular and set up routes](#3.-configure-goangular-and-set-up-routes)
+4. [Permissions service](#4.-permissions-service)
+5. [Main controller](#5.-main-controller)
+6. [Access directive](#6.-access-directive)
+7. [Set up menu and login buttons](#7.-set-up-menu-and-login-buttons)
+8. [Views](#8.-views)
+
### 1. Install
First things first, we include all of our dependencies.
@@ -234,7 +245,7 @@ app.directive('access', function($goConnection, permissions) {
});
```
-### 7. Set up the menu and login buttons
+### 7. Set up menu and login buttons
Time to get back to the view and put our new `access` directive to good use.
@@ -276,7 +287,7 @@ model using the `$local` property to display their name.
```
-### 8. Add the views
+### 8. Views
We defined our routes in **Step 3**, now lets add the corresponding views.
@@ -324,8 +335,13 @@ id, and email (if available).
```
+### Conclusion
+
That's it! We created an app that handles both authentication and user
permissions without any back-end set up. To test the how the `/profile` route
permissions work, try navigating to `/profile` directly in the browser. As a
guest user the link to that view will not be displayed, instead you will be
redirected to the `restricted` view.
+
+Using the concepts covered in this example you are now ready to start writing
+your own GoAngular app using [$goUsers](../users.md) and auth with [$goConnection](../connection.md).
diff --git a/docs/v1/examples/hierarchy.json b/docs/v1/examples/hierarchy.json
index 75fe24b..990fa25 100644
--- a/docs/v1/examples/hierarchy.json
+++ b/docs/v1/examples/hierarchy.json
@@ -1 +1 @@
-[ "__root", "auth" ]
+[ "__root", "key", "auth" ]
diff --git a/docs/v1/examples/index.md b/docs/v1/examples/index.md
index 4ce5d99..d1756eb 100644
--- a/docs/v1/examples/index.md
+++ b/docs/v1/examples/index.md
@@ -4,6 +4,5 @@ Each example will walk you through building a simple app based on a specific
GoAngular concept or feature. Included with the example is a link to the source
code, which you can download and run yourself.
-1. [Users and Authentication](./auth.md)
-
-More Examples coming soon!
+1. [Key Models and Filtering](./key.md)
+2. [Users and Authentication](./auth.md)
diff --git a/docs/v1/examples/key.md b/docs/v1/examples/key.md
new file mode 100644
index 0000000..cf976d0
--- /dev/null
+++ b/docs/v1/examples/key.md
@@ -0,0 +1,405 @@
+# Key Models and Filtering
+
+The GoAngular key example demonstrates how to use [$goKey](../key.md) and [keyFilter](../key_filter.md)
+to model and organize your data in a simple question and answer style app.
+
+The full source of this example can be found [here](https://github.com/colinmacdonald/goangular-key-example).
+
+## Table of Contents
+
+1. [Install](#1.-install)
+2. [Set up view](#2.-set-up-view)
+3. [Configure GoAngular and set up routes](#3.-configure-goangular-and-set-up-routes)
+4. [Main controller](#4.-main-controller)
+5. [Ask controller](#5.-ask-controller)
+6. [Question controller](#6.-question-controller)
+7. [Comment directives](#7.-comment-directives)
+8. [Views](#8.-views)
+
+### 1. Install
+
+First things first, we include all of our dependencies.
+
+```html
+
+ GoInstant GoAngular Auth Example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 2. Set up view
+
+Next, we define our app and main controller in the view. We also set up links in
+the navigation bar for switching between views.
+
+For a guide on `$goUsers` and `users.$local` checkout the [Users and Authentication example](./auth.md).
+
+```html
+
+
+
+```
+
+### 3. Configure GoAngular and set up routes
+
+First create the Angular app with our `ngRoute` and `goangular`
+dependencies, then we configure it with our GoInstant `connectUrl`.
+
+```js
+var app = angular.module('keyExample', ['ngRoute', 'goangular']);
+
+app.config(['$routeProvider', '$goConnectionProvider',
+ function($routeProvider, $goConnectionProvider) {
+ var url = window.connectUrl || 'YOUR_CONNECT_URL';
+
+ $goConnectionProvider.$set(url);
+
+ $routeProvider
+ .when('/recent', {
+ templateUrl: 'views/recent.html',
+ controller: 'recentCtrl'
+ })
+ .when('/ask', {
+ templateUrl: 'views/ask.html',
+ controller: 'askCtrl'
+ })
+ .when('/question/:id', {
+ templateUrl: 'views/question.html',
+ controller: 'questionCtrl'
+ })
+ .when('/search', {
+ templateUrl: 'views/search.html',
+ controller: 'searchCtrl'
+ })
+ .otherwise({
+ redirectTo: '/recent'
+ });
+ }
+]);
+```
+
+### 4. Main controller
+
+Our main controller is very simple in this example. It simply puts our questions
+model and `$local` user's model on scope.
+
+```js
+app.controller('mainCtrl', function($scope, $goKey, $goUsers) {
+ $scope.questions = $goKey('questions').$sync();
+
+ $scope.users = $goUsers();
+ $scope.users.$self();
+});
+```
+
+The recent view's controller will be very basic, so lets define that as well.
+
+```js
+app.controller('recentCtrl', function($scope) {
+ $scope.title = 'Recent Questions';
+});
+```
+
+### 5. Ask controller
+
+The ask controller will handle a new question being submitted. The controller
+simply assembles the data we wish to store in GoInstant on a `question` object,
+then performs an [$add](../model/key_model/add.md) on our root `questions` key.
+Once the `$add` operation completes we redirect the user to the newly created
+question page.
+
+```js
+app.controller('askCtrl', function($scope, $location, $timeout) {
+ $scope.title = 'Ask a Question';
+ $scope.buttonText = 'Ask!';
+
+ $scope.ask = function() {
+ $scope.buttonText = 'Loading...';
+
+ var question = {
+ title: $scope.questionTitle,
+ body: $scope.questionBody,
+ user: $scope.users.$local.displayName
+ };
+
+ $scope.questionTitle = '';
+ $scope.questionBody = '';
+
+ $scope.questions.$add(question).then(function(result) {
+ var id = result.context.addedKey.split('/').pop();
+
+ $timeout(function() {
+ $location.path('/question/' + id);
+ $scope.buttonText = 'Ask!';
+ }, 500);
+ });
+ };
+});
+```
+
+### 6. Question controller
+
+In the question controller we put the question's comments model on
+`$scope`, then extend it with a method for posting a new comment. The `$post`
+method calls [$add](../model/key_model/add.md) to store the comment in
+GoInstant, then clears the input box if the `$add` was successful.
+
+```js
+app.controller('questionCtrl', function($scope, $routeParams, $timeout, $goKey) {
+ $scope.id = $routeParams.id;
+
+ $scope.comments = $goKey('comments').$key($scope.id).$sync();
+
+ $scope.comments.$post = function() {
+ var comment = {
+ body: $scope.newComment,
+ user: $scope.users.$local.displayName,
+ userId: $scope.users.$local.id
+ };
+
+ $scope.comments.$add(comment).then(function() {
+ $scope.newComment = '';
+ });
+ };
+```
+
+Next we add a listener for when a new comment is added to the comments model.
+We use this to display a "New Comment" notification for 2 seconds.
+
+```js
+ var timeoutId = null;
+
+ $scope.comments.$on('add', { local: true }, function() {
+ $scope.notification = true;
+
+ $timeout.cancel(timeoutId);
+
+ timeoutId = $timeout(function() {
+ $scope.notification = false;
+ timeoutId = null;
+ }, 2000);
+ });
+```
+
+Finally, we call [$off](../model/key_model/off.md) on the question's comments
+model to both desynchronize it and remove our `add` listener. This is simply a
+clean-up operation so we are not receiving unnecessary data while in a different
+view.
+
+```js
+ $scope.$on('$destroy', function() {
+ $scope.comments.$off();
+ });
+});
+```
+
+### 7. Comment directives
+
+Question comments are split into two directives. The `comments` directive is
+used as the interface for creating the comments list and is the parent of the
+`comment` directive.
+
+```js
+app.directive('comments', function() {
+ return {
+ scope: {
+ comments: '=',
+ localUser: '=localUser'
+ },
+ restrict: 'A',
+ templateUrl: 'templates/comments.html'
+ };
+});
+```
+
+##### Comments template:
+
+```html
+
+
+
+
+
+```
+
+The comment directive handles the interface for individual comment operations,
+such as editing or deleting a comment.
+
+Given the `id` of the comment we can edit its message by calling [$set](../model/key_model/set.md)
+on the `body` key to overwrite its current value to the value of
+`$scope.editText`. Similarly, we call [$remove](../model/key_model/remove.md)
+on the comment key to delete the message in GoInstant.
+
+```js
+app.directive('comment', function($goKey) {
+ return {
+ restrict: 'E',
+ templateUrl: 'templates/comment.html',
+ require: '^comments',
+ controller: function($scope) {
+ $scope.editButton = 'Edit';
+
+ $scope.comment.$edit = function(id) {
+ if ($scope.editButton === 'Edit') {
+ $scope.editButton = 'Submit';
+
+ } else {
+ var commentBody = $scope.comments.$key(id).$key('body');
+
+ commentBody.$set($scope.editText).then(function() {
+ $scope.editText = '';
+ $scope.editButton = 'Edit';
+ });
+ }
+ };
+
+ $scope.comment.$delete = function(id) {
+ $scope.comments.$key(id).$remove();
+ };
+ }
+ };
+});
+```
+
+##### Comment template:
+
+```html
+
+
+ {{comment.body}} - {{comment.user}}
+
+
+ {{editButton}}
+ Delete
+
+```
+
+### 8. Views
+
+Now that we have our controllers and directives implemented, we can set up our
+four views.
+
+##### Recent view
+
+The recent view iterates over all questions. Using the [keyFilter](../key_filter.md)
+the questions model is converted into an array, which can be sorted limited to
+display the ten most recently asked questions.
+
+```html
+
+```
+
+##### Ask view
+
+The ask view has a number of inputs for creating a new question.
+
+```html
+
+
{{title}}
+
Ask your question below!
+
+
+
+
+```
+
+##### Search view
+
+Similar to the [recent view](#recent-view), the search view displays the top 10
+search results given the search terms.
+
+```html
+
+```
+
+##### Question view
+
+The question view handles display the data retrived from GoInstant given a
+question `id`. It also provides the interface for commenting on a question using
+the [comment directives](#7.-comment-directives) that we created in **step 7**
+
+```html
+
+
{{questions[id].title}}
+
{{questions[id].user}}
+
{{questions[id].body}}
+
+
+
{{(comments | keyFilter).length}} Comments
+ New Comment
+
+
+
New Comment
+
+
+
+
+```
+
+### Conclusion
+
+We created a simple "question and answer" app which handles storing, filtering,
+structuring, and manipulating data using [$goKey](../key.md). We encourage you
+to run the example locally, try populating the app with some data, and
+experiment with the code.
+
+Using the concepts covered in this example you are now ready to start writing
+your own GoAngular app using [$goKey](../key.md) and the [keyFilter](../key_filter.md).