diff --git a/resources/frontend_client/app/components/DashboardsDropdown.react.js b/resources/frontend_client/app/components/DashboardsDropdown.react.js
new file mode 100644
index 0000000000000000000000000000000000000000..72361fbced5b94203a169df264e00ac14fba2fd6
--- /dev/null
+++ b/resources/frontend_client/app/components/DashboardsDropdown.react.js
@@ -0,0 +1,131 @@
+"use strict";
+
+import React, { Component, PropTypes } from 'react';
+import _ from "underscore";
+import cx from "classnames";
+import OnClickOut from 'react-onclickout';
+
+import CreateDashboardModal from "metabase/components/CreateDashboardModal.react";
+import Icon from "metabase/components/Icon.react";
+import Modal from "metabase/components/Modal.react";
+
+
+export default class DashboardsDropdown extends Component {
+
+    constructor(props) {
+        super(props);
+
+        this.state = {
+            dropdownOpen: false,
+            modalOpen: false
+        };
+
+        _.bindAll(this, "toggleDropdown", "closeDropdown", "toggleModal", "closeModal");
+    }
+
+    onCreateDashboard(newDashboard) {
+        let { createDashboardFn } = this.props;
+
+        createDashboardFn(newDashboard).then(function() {
+            // close modal and add new dash to our dashboards list
+            this.setState({
+                dropdownOpen: false,
+                modalOpen: false
+            });
+        }.bind(this));
+    }
+
+    toggleModal() {
+        if (!this.state.modalOpen) {
+            // when we open our modal we always close the dropdown
+            this.setState({
+                dropdownOpen: false,
+                modalOpen: !this.state.modalOpen
+            });
+        }
+    }
+
+    closeModal() {
+        this.setState({ modalOpen: false });
+    }
+
+    toggleDropdown() {
+        this.setState({ dropdownOpen: !this.state.dropdownOpen });
+    }
+
+    closeDropdown() {
+        this.setState({ dropdownOpen: false });
+    }
+
+    renderCreateDashboardModal() {
+        return (
+            <Modal>
+                <CreateDashboardModal
+                    createDashboardFn={this.onCreateDashboard.bind(this)}
+                    closeFn={this.closeModal} />
+            </Modal>
+        );
+    }
+
+    render() {
+        let { dashboards } = this.props;
+        let { dropdownOpen, modalOpen } = this.state;
+
+        return (
+            <div>
+                { modalOpen ? this.renderCreateDashboardModal() : null }
+
+                <OnClickOut onClickOut={this.closeDropdown}>
+                    <div className={cx('NavDropdown inline-block cursor-pointer', { 'open': dropdownOpen })}>
+                        <a className="NavDropdown-button NavItem text-white cursor-pointer p2 flex align-center" onClick={this.toggleDropdown}>
+                            <span className="NavDropdown-button-layer">
+                                Dashboards
+                                <Icon className="ml1" name={'chevrondown'} width={8} height={8}></Icon>
+                            </span>
+                        </a>
+
+                        { dropdownOpen ?
+                            <div className="NavDropdown-content DashboardList">
+                                { dashboards.length === 0 ?
+                                    <div className="NavDropdown-content-layer text-white text-centered">
+                                        <div className="p2"><span className="QuestionCircle">?</span></div>
+                                        <div className="px2 py1 text-bold">You don’t have any dashboards yet.</div>
+                                        <div className="px2 pb2 text-light">Dashboards group visualizations for frequent questions in a single handy place.</div>
+                                        <div className="border-top border-light">
+                                            <a className="Dropdown-item block text-white no-decoration" href="#" onClick={this.toggleModal}>Create a new dashboard</a>
+                                        </div>
+                                    </div>
+                                :
+                                    <ul className="NavDropdown-content-layer">
+                                        { dashboards.map(dash =>
+                                            <li className="block">
+                                                <a className="Dropdown-item block text-white no-decoration" href={"/dash/"+dash.id} onClick={this.closeDropdown}>
+                                                    <div className="flex text-bold">
+                                                        {dash.name}
+                                                    </div>
+                                                    { dash.description ?
+                                                        <div className="mt1 text-light text-brand-light">
+                                                            {dash.description}
+                                                        </div>
+                                                    : null }
+                                                </a>
+                                            </li>
+                                        )}
+                                        <li className="block border-top border-light">
+                                            <a className="Dropdown-item block text-white no-decoration" href="#" onClick={this.toggleModal}>Create a new dashboard</a>
+                                        </li>
+                                    </ul>
+                                }
+                            </div>
+                        : null }
+                    </div>
+                </OnClickOut>
+            </div>
+        );
+    }
+}
+
+DashboardsDropdown.propTypes = {
+    createDashboardFn: PropTypes.func.isRequired,
+    dashboards: PropTypes.array.isRequired
+};
diff --git a/resources/frontend_client/app/components/LogoIcon.react.js b/resources/frontend_client/app/components/LogoIcon.react.js
index 046b5b59dd5bf2576451e1c0301c33384494368e..985c15b424919bae09257122c2fc00a25b50b892 100644
--- a/resources/frontend_client/app/components/LogoIcon.react.js
+++ b/resources/frontend_client/app/components/LogoIcon.react.js
@@ -18,7 +18,12 @@ export default class LogoIcon extends React.Component {
     }
 }
 
-LogoIcon.PropTypes = {
-	width: PropTypes.number.isRequired,
-    height: PropTypes.number.isRequired
+LogoIcon.defaultProps = {
+    height: 32,
+    width: 32
+}
+
+LogoIcon.propTypes = {
+	width: PropTypes.number,
+    height: PropTypes.number
 }
\ No newline at end of file
diff --git a/resources/frontend_client/app/components/Navbar.react.js b/resources/frontend_client/app/components/Navbar.react.js
new file mode 100644
index 0000000000000000000000000000000000000000..1785310f51fea1133fbd6689d357e09bf294a54c
--- /dev/null
+++ b/resources/frontend_client/app/components/Navbar.react.js
@@ -0,0 +1,120 @@
+"use strict";
+
+import React, { Component, PropTypes } from 'react';
+import cx from "classnames";
+
+import DashboardsDropdown from "metabase/components/DashboardsDropdown.react";
+import Icon from "metabase/components/Icon.react";
+import LogoIcon from "metabase/components/LogoIcon.react";
+import ProfileLink from "metabase/components/ProfileLink.react";
+
+
+// TODO - this relies on props.location, which is angular's $location service
+
+export default class Navbar extends Component {
+
+    isActive(path) {
+        return this.props.location.path().indexOf(path) >= 0;
+    }
+
+    renderAdminNav() {
+        const classes = "NavItem py1 px2 no-decoration";
+
+        return (
+            <nav className="AdminNav">
+                <div className="wrapper flex align-center">
+                    <div className="NavTitle flex align-center">
+                        <Icon name={'gear'} className="AdminGear" width={22} height={22}></Icon>
+                        <span className="NavItem-text ml1 hide sm-show">Site Administration</span>
+                    </div>
+
+                    <ul className="sm-ml4 flex flex-full">
+                        <li>
+                            <a className={cx(classes, {"is--selected": this.isActive("/admin/settings")})}  href="/admin/settings/">
+                                Settings
+                            </a>
+                        </li>
+                        <li>
+                            <a className={cx(classes, {"is--selected": this.isActive("/admin/people")})} href="/admin/people/">
+                                People
+                            </a>
+                        </li>
+                        <li>
+                            <a className={cx(classes, {"is--selected": this.isActive("/admin/metadata")})} href="/admin/metadata/">
+                                Metadata
+                            </a>
+                        </li>
+                        <li>
+                            <a className={cx(classes, {"is--selected": this.isActive("/admin/databases")})} href="/admin/databases/">
+                                Databases
+                            </a>
+                        </li>
+                    </ul>
+
+                    <ProfileLink {...this.props}></ProfileLink>
+                </div>
+            </nav>
+        );
+    }
+
+    renderAuthNav() {
+        return (
+            <nav className="py2 sm-py1 xl-py3 relative"></nav>
+        );
+    }
+
+    renderEmptyNav() {
+        return (
+            <nav className="py2 sm-py1 xl-py3 relative">
+                <ul className="wrapper flex align-center">
+                    <li>
+                        <a className="NavItem cursor-pointer flex align-center" href="/">
+                            <LogoIcon className="text-brand my2"></LogoIcon>
+                        </a>
+                    </li>
+                </ul>
+            </nav>
+        );
+    }
+
+    renderMainNav() {
+        return (
+            <nav className="CheckBg CheckBg-offset sm-py2 sm-py1 xl-py3 relative bg-brand">
+                <ul className="wrapper flex align-center">
+                    <li>
+                        <a className="NavItem cursor-pointer text-white flex align-center my1" href="/">
+                            <LogoIcon className="text-white m1"></LogoIcon>
+                        </a>
+                    </li>
+                    <li>
+                        <DashboardsDropdown {...this.props}></DashboardsDropdown>
+                    </li>
+                    <li className="flex-align-right">
+                        <a className="rounded inline-block bg-white text-brand cursor-pointer p2 no-decoration" href="/q">New <span className="hide sm-show">Question</span></a>
+                        <div className="inline-block text-white"><ProfileLink {...this.props}></ProfileLink></div>
+                    </li>
+                </ul>
+            </nav>
+        );
+    }
+
+    render() {
+        let { context, user } = this.props;
+
+        if (!user) return null;
+
+        switch (context) {
+            case "admin": return this.renderAdminNav();
+            case "auth": return this.renderAuthNav();
+            case "none": return this.renderEmptyNav();
+            case "setup": return null;
+            default: return this.renderMainNav();
+        }
+    }
+}
+
+Navbar.propTypes = {
+    context: PropTypes.string.isRequired,
+    location: PropTypes.string.isRequired,
+    user: PropTypes.object
+};
diff --git a/resources/frontend_client/app/controllers.js b/resources/frontend_client/app/controllers.js
index e6a80f52b167f690ad5b2246437512edeb9f0011..6227e326ff331da505cbac39ac8d2a2100173540 100644
--- a/resources/frontend_client/app/controllers.js
+++ b/resources/frontend_client/app/controllers.js
@@ -1,5 +1,8 @@
 'use strict';
 
+import Navbar from 'metabase/components/Navbar.react';
+
+
 // Global Controllers
 var MetabaseControllers = angular.module('metabase.controllers', ['metabase.services', 'metabase.navbar.directives']);
 
@@ -47,35 +50,71 @@ MetabaseControllers.controller('NotFound', ['AppState', function(AppState) {
     AppState.setAppContext('none');
 }]);
 
-MetabaseControllers.controller('Nav', ['$scope', '$routeParams', '$location', 'AppState', function($scope, $routeParams, $location, AppState) {
-
-    $scope.isActive = function(location) {
-        return $location.path().indexOf(location) >= 0;
-    };
+MetabaseControllers.controller('Nav', ['$scope', '$routeParams', '$location', '$rootScope', 'AppState', 'Dashboard',
+    function($scope, $routeParams, $location, $rootScope, AppState, Dashboard) {
+
+        function refreshDashboards() {
+            Dashboard.list({
+                'filterMode': 'all'
+            }, function (dashes) {
+                $scope.dashboards = dashes;
+            }, function (error) {
+                console.log('error getting dahsboards list', error);
+            });
+        }
 
-    var setNavContext = function(context) {
-        switch (context) {
-            case "admin":
-                $scope.nav = 'admin';
-                break;
-            case "setup":
-                $scope.nav = 'setup';
-                break;
-            case "auth":
-                $scope.nav = 'auth';
-                break;
-            case "none":
-                $scope.nav = 'none';
-                break;
-            default:
-                $scope.nav = 'main';
+        function setNavContext(context) {
+            switch (context) {
+                case "admin":
+                    $scope.context = 'admin';
+                    break;
+                case "setup":
+                    $scope.context = 'setup';
+                    break;
+                case "auth":
+                    $scope.context = 'auth';
+                    break;
+                case "none":
+                    $scope.context = 'none';
+                    break;
+                default:
+                    $scope.context = 'main';
+            }
         }
-    };
 
-    $scope.$on('appstate:context-changed', function(event, newAppContext) {
-        setNavContext(newAppContext);
-    });
+        $scope.Navbar = Navbar;
+        $scope.location = $location;
 
-    // initialize our state from the current AppState model, which we expect to have resolved already
-    setNavContext(AppState.model.appContext);
-}]);
+        $scope.dashboards = [];
+        $scope.createDashboardFn = async function(newDashboard) {
+            var dashboard = await Dashboard.create(newDashboard).$promise;
+            $rootScope.$broadcast("dashboard:create", dashboard.id);
+            $location.path("/dash/" + dashboard.id);
+
+            // this is important because it allows our caller to perform any of their own actions after the promis resolves
+            return dashboard;
+        };
+
+        $scope.$on('appstate:context-changed', function(event, newAppContext) {
+            setNavContext(newAppContext);
+        });
+
+        $scope.$on("dashboard:create", function(event, dashboardId) {
+            refreshDashboards();
+        });
+
+        $scope.$on("dashboard:delete", function(event, dashboardId) {
+            refreshDashboards();
+        });
+
+        $scope.$on("dashboard:update", function(event, dashboardId) {
+            refreshDashboards();
+        });
+
+        // always initialize with a fresh listing
+        refreshDashboards();
+
+        // initialize our state from the current AppState model, which we expect to have resolved already
+        setNavContext(AppState.model.appContext);
+    }
+]);
diff --git a/resources/frontend_client/app/dashboard/dashboard.controllers.js b/resources/frontend_client/app/dashboard/dashboard.controllers.js
index c383a8d780c1457c4ce9f2c920c8152241138220..51b8d6ee95314b9945e42086052d01c8dafcb6da 100644
--- a/resources/frontend_client/app/dashboard/dashboard.controllers.js
+++ b/resources/frontend_client/app/dashboard/dashboard.controllers.js
@@ -41,32 +41,3 @@ DashboardControllers.controller('Dashboard', ['$scope', '$rootScope', '$routePar
     $scope.store = finalCreateStore(reducer, { selectedDashboard: $routeParams.dashId });
     // $scope.monitor = LogMonitor;
 }]);
-
-DashboardControllers.controller('DashList', ['$scope', '$location', 'Dashboard', function($scope, $location, Dashboard) {
-    $scope.dashboards = [];
-
-    var refreshListing = function() {
-        Dashboard.list({
-            'filterMode': 'all'
-        }, function (dashes) {
-            $scope.dashboards = dashes;
-        }, function (error) {
-            console.log('error getting dahsboards list', error);
-        });
-    };
-
-    $scope.$on("dashboard:create", function(event, dashboardId) {
-        refreshListing();
-    });
-
-    $scope.$on("dashboard:delete", function(event, dashboardId) {
-        refreshListing();
-    });
-
-    $scope.$on("dashboard:update", function(event, dashboardId) {
-        refreshListing();
-    });
-
-    // always initialize with a fresh listing
-    refreshListing();
-}]);
diff --git a/resources/frontend_client/app/dashboard/dashboard.directives.js b/resources/frontend_client/app/dashboard/dashboard.directives.js
deleted file mode 100644
index ac1269708b2d1e408950aa8afa7de495bb4c8cb3..0000000000000000000000000000000000000000
--- a/resources/frontend_client/app/dashboard/dashboard.directives.js
+++ /dev/null
@@ -1,45 +0,0 @@
-'use strict';
-
-import CreateDashboardModal from '../components/CreateDashboardModal.react';
-
-var DashboardDirectives = angular.module('metabase.dashboard.directives', [
-    'metabase.metabase.services',
-]);
-
-DashboardDirectives.directive('mbDashboardCreate', ['Dashboard', '$modal', '$location', '$rootScope',
-    function(Dashboard, $modal, $location, $rootScope) {
-        function link(scope, element, attrs) {
-
-            var openModal = function() {
-                $modal.open({
-                    template: '<div class="Modal" mb-react-component="CreateDashboardModal"></div>',
-                    controller: ['$scope', '$modalInstance',
-                        function($scope, $modalInstance) {
-                            $scope.CreateDashboardModal = CreateDashboardModal;
-                            $scope.createDashboardFn = async function(newDashboard) {
-                                var dashboard = await Dashboard.create(newDashboard).$promise;
-                                $modalInstance.close(dashboard);
-                                $rootScope.$broadcast("dashboard:create", dashboard.id);
-                                $location.path("/dash/" + dashboard.id);
-                            }
-                            $scope.closeFn = function() {
-                                $modalInstance.dismiss('cancel');
-                            };
-                        }
-                    ]
-                });
-            };
-
-            element.bind('click', openModal);
-        }
-
-        return {
-            restrict: 'A',
-            link: link,
-            scope: {
-                callback: '=',
-                dashboard: '='
-            }
-        };
-    }
-]);
diff --git a/resources/frontend_client/app/dashboard/dashboard.module.js b/resources/frontend_client/app/dashboard/dashboard.module.js
index 603db13810cd074fabe6cf5e85955c435b6ba00c..ce3dca6f817944a91e932eecf4828cc9c7fbbf11 100644
--- a/resources/frontend_client/app/dashboard/dashboard.module.js
+++ b/resources/frontend_client/app/dashboard/dashboard.module.js
@@ -7,7 +7,6 @@ var Dashboard = angular.module('metabase.dashboard', [
     'metabase.services',
     'metabase.dashboard.services',
     'metabase.dashboard.controllers',
-    'metabase.dashboard.directives',
     'metabase.card.services'
 ]);
 
diff --git a/resources/frontend_client/index_template.html b/resources/frontend_client/index_template.html
index 14cd4a5538f3b8cb66957e22dd4bdcec07766a54..ae27cbb6f651f8a3fbb287eb824c7bf44ab9602d 100644
--- a/resources/frontend_client/index_template.html
+++ b/resources/frontend_client/index_template.html
@@ -16,110 +16,7 @@
     </head>
 
     <body ng-controller="Metabase">
-        <div class="Nav" ng-controller="Nav" ng-if="user" ng-cloak>
-            <!-- MAIN NAV -->
-            <nav class="CheckBg CheckBg-offset sm-py2 sm-py1 xl-py3 relative bg-brand" ng-show="nav === 'main'">
-                <ul class="wrapper flex align-center">
-                    <li>
-                        <a class="NavItem cursor-pointer text-white flex align-center my1" href="/">
-                            <mb-logo-icon class="text-white m1"></mb-logo-icon>
-                        </a>
-                    </li>
-                    <li>
-                        <div class="NavDropdown ml1 md-ml3" dropdown on-toggle="toggled(open)">
-                            <a class="NavDropdown-button NavItem text-white cursor-pointer p2 flex align-center" dropdown-toggle>
-                                <span class="NavDropdown-button-layer">
-                                    Dashboards
-                                    <mb-icon class="ml1" name="chevrondown" width="8px" height="8px"></mb-icon>
-                                </span>
-                            </a>
-                            <div class="NavDropdown-content DashboardList" ng-controller="DashList">
-                                <div class="NavDropdown-content-layer text-white text-centered" ng-if="dashboards.length === 0">
-                                    <div class="p2"><span class="QuestionCircle">?</span></div>
-                                    <div class="px2 py1 text-bold">You don’t have any dashboards yet.</div>
-                                    <div class="px2 pb2 text-light">Dashboards group visualizations for frequent questions in a single handy place.</div>
-                                    <div class="border-top border-light">
-                                        <a class="Dropdown-item block text-white no-decoration" href="#" mb-dashboard-create>Create a new dashboard</a>
-                                    </div>
-                                </div>
-                                <ul class="NavDropdown-content-layer" ng-if="dashboards.length > 0">
-                                    <li class="block" ng-repeat="dash in dashboards">
-                                        <a class="Dropdown-item block text-white no-decoration" href="/dash/{{dash.id}}">
-                                            <div class="flex text-bold">
-                                                {{dash.name}}
-                                                <mb-icon class="ml1 flex flex-align-right align-center" name="lock" width="12px" height="12px" ng-if="dash.public_perms === 0"></mb-icon>
-                                            </div>
-                                            <div class="mt1 text-light text-brand-light" ng-if="dash.description">
-                                                {{dash.description}}
-                                            </div>
-                                        </a>
-                                    </li>
-                                    <li class="block border-top border-light">
-                                        <a class="Dropdown-item block text-white no-decoration" href="#" mb-dashboard-create>Create a new dashboard</a>
-                                    </li>
-                                </ul>
-                            </div>
-                        </div>
-                    </li>
-                    <li class="flex-align-right">
-                        <a class="rounded inline-block bg-white text-brand cursor-pointer p2 no-decoration" href="/q">New <span class="hide sm-show">Question</span></a>
-                        <div mb-profile-link class="inline-block text-white" user="user" context="nav"></div>
-                    </li>
-                </ul>
-            </nav>
-
-            <!-- ADMIN NAV -->
-            <nav class="AdminNav" ng-show="nav === 'admin'">
-                <div class="wrapper flex align-center">
-                    <div class="NavTitle flex align-center">
-                        <mb-icon name="gear" class="AdminGear" width="22px" height="22px"></mb-icon>
-                        <span class="NavItem-text ml1 hide sm-show">Site Administration</span>
-                    </div>
-
-                    <!-- admin sections -->
-                    <ul class="sm-ml4 flex flex-full">
-                        <li>
-                            <a class="NavItem py1 px2 no-decoration" ng-class="{ 'is--selected' : isActive('/admin/settings')}" href="/admin/settings/">
-                                Settings
-                            </a>
-                        </li>
-                        <li>
-                            <a class="NavItem py1 px2 no-decoration" ng-class="{ 'is--selected' : isActive('/admin/people')}" href="/admin/people/">
-                                People
-                            </a>
-                        </li>
-                        <li>
-                            <a class="NavItem py1 px2 no-decoration" ng-class="{ 'is--selected' : isActive('/admin/metadata')}" href="/admin/metadata/">
-                                Metadata
-                            </a>
-                        </li>
-                        <li>
-                            <a class="NavItem py1 px2 no-decoration" ng-class="{ 'is--selected' : isActive('/admin/databases')}" href="/admin/databases/">
-                                Databases
-                            </a>
-                        </li>
-                    </ul>
-
-                    <!-- user profile dropdown -->
-                    <div mb-profile-link user="user" context="nav"></div>
-                </div>
-            </nav>
-
-            <!-- AUTH NAV -->
-            <nav class="py2 sm-py1 xl-py3 relative" ng-show="nav === 'auth'">
-            </nav>
-
-            <!-- NO NAV -->
-            <nav class="py2 sm-py1 xl-py3 relative" ng-show="nav === 'none'">
-                <ul class="wrapper flex align-center">
-                    <li>
-                        <a class="NavItem cursor-pointer flex align-center" href="/">
-                            <mb-logo-icon class="text-brand my2"></mb-logo-icon>
-                        </a>
-                    </li>
-                </ul>
-            </nav>
-        </div>
+        <div class="Nav" ng-controller="Nav" mb-react-component="Navbar"></div>
 
         <main class="Main flex flex-column flex-full" ng-view></main>
     </body>