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..2f7dd53a2fbabb5bc5d5334a185f16079deaadf4
--- /dev/null
+++ b/resources/frontend_client/app/components/DashboardsDropdown.react.js
@@ -0,0 +1,140 @@
+"use strict";
+
+import React, { Component, PropTypes } from 'react';
+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
+        };
+
+        this.toggleDropdown = this.toggleDropdown.bind(this);
+        this.closeDropdown = this.closeDropdown.bind(this);
+        this.toggleModal = this.toggleModal.bind(this);
+        this.closeModal = this.closeModal.bind(this);
+    }
+
+    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;
+
+        let dropDownClasses = cx({
+            'NavDropdown': true,
+            'inline-block': true,
+            'cursor-pointer': true,
+            'open': dropdownOpen,
+        })
+
+        return (
+            <div>
+                { modalOpen ? this.renderCreateDashboardModal() : null }
+
+                <OnClickOut onClickOut={this.closeDropdown}>
+                    <div className={dropDownClasses}>
+                        <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/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/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>