diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 3fa504018264236b73f5979d12ae81ae29779ff6..de567d04d9487aa3784ce3f88c9d6facb272d44c 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -65,8 +65,11 @@ phutil_register_library_map(array(
     'SprintPoints' => 'util/SprintPoints.php',
     'SprintProjectController' => 'controller/SprintProjectController.php',
     'SprintProjectCustomField' => 'customfield/SprintProjectCustomField.php',
+    'SprintProjectDetailsProfilePanel' => 'engine/SprintProjectDetailsProfilePanel.php',
     'SprintProjectProfileController' => 'controller/SprintProjectProfileController.php',
+    'SprintProjectProfilePanelEngine' => 'engine/SprintProjectProfilePanelEngine.php',
     'SprintProjectViewController' => 'controller/SprintProjectViewController.php',
+    'SprintProjectWorkboardProfilePanel' => 'profilepanel/SprintProjectWorkboardProfilePanel.php',
     'SprintQuery' => 'query/SprintQuery.php',
     'SprintQueryTest' => 'tests/SprintQueryTest.php',
     'SprintReportBurnUpView' => 'view/reports/SprintReportBurnUpView.php',
@@ -105,7 +108,7 @@ phutil_register_library_map(array(
     'SprintBoardColumnDetailController' => 'SprintBoardController',
     'SprintBoardColumnEditController' => 'SprintBoardController',
     'SprintBoardColumnHideController' => 'SprintBoardController',
-    'SprintBoardController' => 'SprintController',
+    'SprintBoardController' => 'SprintProjectController',
     'SprintBoardImportController' => 'SprintBoardController',
     'SprintBoardMoveController' => 'SprintBoardController',
     'SprintBoardReorderController' => 'SprintBoardController',
@@ -140,8 +143,11 @@ phutil_register_library_map(array(
       'PhabricatorProjectCustomField',
       'PhabricatorStandardCustomFieldInterface',
     ),
+    'SprintProjectDetailsProfilePanel' => 'PhabricatorProfilePanel',
     'SprintProjectProfileController' => 'SprintProjectController',
+    'SprintProjectProfilePanelEngine' => 'PhabricatorProfilePanelEngine',
     'SprintProjectViewController' => 'SprintController',
+    'SprintProjectWorkboardProfilePanel' => 'PhabricatorProfilePanel',
     'SprintQuery' => 'SprintDAO',
     'SprintQueryTest' => 'SprintTestCase',
     'SprintReportBurnUpView' => 'SprintView',
diff --git a/src/controller/SprintController.php b/src/controller/SprintController.php
index 02947e69dfbe75421ad953eaa69863b827dd9c51..a05d62535599f5bce1e2f29876be3ffd0ddb64d0 100644
--- a/src/controller/SprintController.php
+++ b/src/controller/SprintController.php
@@ -118,62 +118,6 @@ abstract class SprintController extends PhabricatorController {
     return $id;
   }
 
-  public function buildIconNavView(PhabricatorProject $project) {
-    $nav = $this->buildSprintIconNavView($project);
-    $nav->selectFilter(null);
-    return $nav;
-  }
-
-  public function buildSprintIconNavView(PhabricatorProject $project) {
-    $viewer = $this->getViewer();
-    $id = $project->getID();
-    $picture = $project->getProfileImageURI();
-    $name = $project->getName();
-    $enable_phragile = PhabricatorEnv::getEnvConfig('sprint.enable-phragile');
-    $phragile_base_uri = PhabricatorEnv::getEnvConfig('sprint.phragile-uri');
-    $phragile_uri = new PhutilURI($phragile_base_uri.$id);
-    $columns = id(new PhabricatorProjectColumnQuery())
-        ->setViewer($viewer)
-        ->withProjectPHIDs(array($project->getPHID()))
-        ->execute();
-    if ($columns) {
-      $board_icon = 'fa-columns';
-    } else {
-      $board_icon = 'fa-columns grey';
-    }
-
-    $nav = new AphrontSideNavFilterView();
-    $nav->setIconNav(true);
-    if ($this->isSprint($project) !== false) {
-      $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
-      $nav->addIcon("profile/{$id}/", $name, null, $picture, null);
-      $nav->addIcon("burn/{$id}/", pht('Burndown'), 'fa-fire', null, null);
-      if ($enable_phragile) {
-        $nav->addIcon("sprints/{$id}/", pht('Phragile'), 'fa-pie-chart', null, $phragile_uri);
-      }
-      $nav->addIcon("board/{$id}/", pht('Sprint Board'), $board_icon, null, null);
-      $nav->addIcon('.', pht('Sprint List'), 'fa-bar-chart', null, null);
-    } else {
-      $nav->setBaseURI(new PhutilURI($this->getProjectsURI()));
-      $nav->addIcon("profile/{$id}/", $name, null, $picture);
-      $nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon);
-    }
-    $class = 'PhabricatorManiphestApplication';
-    if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
-      $phid = $project->getPHID();
-      $query_uri = urisprintf(
-          '/maniphest/?statuses=open()&projects=%s#R',
-          $phid);
-      $nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri);
-    }
-
-    $nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o', null, null);
-    $nav->addIcon("members/{$id}/", pht('Members'), 'fa-group', null, null);
-    $nav->addIcon("edit/{$id}/", pht('Edit Details'), 'fa-pencil', null, null);
-
-    return $nav;
-  }
-
   protected function isSprint($object) {
     $validator = new SprintValidator();
     $issprint = call_user_func(array($validator, 'checkForSprint'),
diff --git a/src/controller/SprintDataViewController.php b/src/controller/SprintDataViewController.php
index 50390f6b240bf36445c63a10eebcb0b7a989c5fc..5113cfffae4f3821e19b6f1cedcb7c3e7d7bbce2 100755
--- a/src/controller/SprintDataViewController.php
+++ b/src/controller/SprintDataViewController.php
@@ -6,12 +6,21 @@ final class SprintDataViewController extends SprintController {
   private $request;
   private $viewer;
   private $project;
+  private $profileMenu;
 
-  public function buildIconNavView(PhabricatorProject $project) {
-    $id = $project->getID();
-    $nav = parent::buildIconNavView($project);
-    $nav->selectFilter("burn/{$id}/");
-    return $nav;
+  public function getProfileMenu(PhabricatorProject $project) {
+    if (!$this->profileMenu) {
+      if ($project) {
+        $viewer = $this->getViewer();
+
+        $engine = id(new SprintProjectProfilePanelEngine())
+            ->setViewer($viewer)
+            ->setProfileObject($project);
+
+        $this->profileMenu = $engine->buildNavigation();
+      }
+    }
+    return $this->profileMenu;
   }
 
   public function handleRequest(AphrontRequest $request) {
@@ -35,19 +44,14 @@ final class SprintDataViewController extends SprintController {
     $can_create = $this->hasApplicationCapability(
         ProjectCreateProjectsCapability::CAPABILITY);
     $crumbs = $this->getCrumbs($can_create);
-    $nav = $this->buildIconNavView($this->project);
-    $nav->appendChild(
-        array($crumbs,
-              $error_box,
-              $sprintdata_view,
-        ));
-
-    return $this->buildApplicationPage(
-        $nav,
-        array(
-            'title' => array(pht('Burndown'), $this->project->getName()),
-            'device' => true,
-        ));
+    $nav = $this->getProfileMenu($this->project);
+    return $this->newPage()
+        ->setNavigation($nav)
+        ->setCrumbs($crumbs)
+        ->setTitle($this->project->getName())
+        ->setPageObjectPHIDs(array($this->project->getPHID()))
+        ->appendChild($error_box)
+        ->appendChild($sprintdata_view);
   }
 
   public function loadProject() {
diff --git a/src/controller/SprintProjectController.php b/src/controller/SprintProjectController.php
index 8866971f7956d6df0524907f420eea50e96e1862..52a9eef5dc107536b33b070f31e6fe309c5f7024 100644
--- a/src/controller/SprintProjectController.php
+++ b/src/controller/SprintProjectController.php
@@ -3,6 +3,7 @@
 abstract class SprintProjectController extends SprintController {
 
   private $project;
+  private $profileMenu;
 
   protected function setProject(PhabricatorProject $project) {
     $this->project = $project;
@@ -80,7 +81,33 @@ abstract class SprintProjectController extends SprintController {
   }
 
   public function buildApplicationMenu() {
-    return $this->buildSideNavView(true)->getMenu();
+    $menu = $this->newApplicationMenu();
+
+    $profile_menu = $this->getProfileMenu();
+    if ($profile_menu) {
+      $menu->setProfileMenu($profile_menu);
+    }
+
+    $menu->setSearchEngine(new PhabricatorProjectSearchEngine());
+
+    return $menu;
+  }
+
+  protected function getProfileMenu() {
+    if (!$this->profileMenu) {
+      $project = $this->getProject();
+      if ($project) {
+        $viewer = $this->getViewer();
+
+        $engine = id(new SprintProjectProfilePanelEngine())
+            ->setViewer($viewer)
+            ->setProfileObject($project);
+
+        $this->profileMenu = $engine->buildNavigation();
+      }
+    }
+
+    return $this->profileMenu;
   }
 
   public function buildSideNavView($for_app = false) {
@@ -115,66 +142,6 @@ abstract class SprintProjectController extends SprintController {
     return $nav;
   }
 
-  public function buildIconNavView(PhabricatorProject $project) {
-    $this->setProject($project);
-    $viewer = $this->getViewer();
-    $id = $project->getID();
-    $picture = $project->getProfileImageURI();
-    $name = $project->getName();
-    $enable_phragile = PhabricatorEnv::getEnvConfig('sprint.enable-phragile');
-    $phragile_base_uri = PhabricatorEnv::getEnvConfig('sprint.phragile-uri');
-    $phragile_uri = new PhutilURI($phragile_base_uri.$id);
-
-    $columns = id(new PhabricatorProjectColumnQuery())
-        ->setViewer($viewer)
-        ->withProjectPHIDs(array($project->getPHID()))
-        ->execute();
-    if ($columns) {
-      $board_icon = 'fa-columns';
-    } else {
-      $board_icon = 'fa-columns grey';
-    }
-
-    $nav = new AphrontSideNavFilterView();
-    $nav->setIconNav(true);
-    $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
-    if ($this->isSprint($project) !== false) {
-      $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
-      $nav->addIcon("profile/{$id}/", $name, null, $picture, null);
-      $nav->addIcon("burn/{$id}/", pht('Burndown'), 'fa-fire', null, null);
-      if ($enable_phragile) {
-        $nav->addIcon("sprints/{$id}/", pht('Phragile'), 'fa-pie-chart', null, $phragile_uri);
-      }
-      $nav->addIcon("board/{$id}/", pht('Sprint Board'), $board_icon, null, null);
-      $nav->addIcon('.', pht('Sprint List'), 'fa-bar-chart', null, null);
-    } else {
-      $nav->setBaseURI(new PhutilURI($this->getProjectsURI()));
-      $nav->addIcon("profile/{$id}/", $name, null, $picture);
-      $nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon);
-    }
-    $class = 'PhabricatorManiphestApplication';
-    if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
-      $phid = $project->getPHID();
-
-      $query_uri = urisprintf(
-          '/maniphest/?statuses=open()&projects=%s#R',
-          $phid);
-      $nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri);
-    }
-
-    $nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o');
-    $nav->addIcon("members/{$id}/", pht('Members'), 'fa-group');
-    $nav->addIcon("details/{$id}/", pht('Edit Details'), 'fa-pencil');
-
-    if (PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
-      $nav->addIcon("subprojects/{$id}/", pht('Subprojects'), 'fa-sitemap');
-      $nav->addIcon("milestones/{$id}/", pht('Milestones'), 'fa-map-marker');
-    }
-
-
-    return $nav;
-  }
-
   protected function buildApplicationCrumbs() {
     $crumbs = parent::buildApplicationCrumbs();
 
diff --git a/src/controller/SprintProjectProfileController.php b/src/controller/SprintProjectProfileController.php
index addd70f6fbef2c629ae4d2948ff7da936a74fb85..46d00a23a5181eaffb565ffc4e53daf65617d3ba 100644
--- a/src/controller/SprintProjectProfileController.php
+++ b/src/controller/SprintProjectProfileController.php
@@ -44,8 +44,8 @@ final class SprintProjectProfileController
         new PhabricatorProjectTransactionQuery());
     $timeline->setShouldTerminate(true);
 
-    $nav = $this->buildIconNavView($project);
-    $nav->selectFilter("profile/{$id}/");
+    $nav = $this->getProfileMenu();
+    $nav->selectFilter(PhabricatorProject::PANEL_PROFILE);
     $crumbs = $this->buildApplicationCrumbs();
 
     return $this->newPage()
@@ -76,7 +76,9 @@ final class SprintProjectProfileController
         id(new PhabricatorActionView())
             ->setName(pht('Edit Details'))
             ->setIcon('fa-pencil')
-            ->setHref($this->getApplicationURI("edit/{$id}/")));
+            ->setHref($this->getApplicationURI("edit/{$id}/"))
+            ->setDisabled(!$can_edit)
+            ->setWorkflow(!$can_edit));
 
     $view->addAction(
         id(new PhabricatorActionView())
@@ -104,6 +106,26 @@ final class SprintProjectProfileController
               ->setWorkflow(true));
     }
 
+    $can_lock = $can_edit && $this->hasApplicationCapability(
+            ProjectCanLockProjectsCapability::CAPABILITY);
+
+    if ($project->getIsMembershipLocked()) {
+      $lock_name = pht('Unlock Project');
+      $lock_icon = 'fa-unlock';
+    } else {
+      $lock_name = pht('Lock Project');
+      $lock_icon = 'fa-lock';
+    }
+
+    $view->addAction(
+        id(new PhabricatorActionView())
+            ->setName($lock_name)
+            ->setIcon($lock_icon)
+            ->setHref($this->getApplicationURI("lock/{$id}/"))
+            ->setDisabled(!$can_lock)
+            ->setWorkflow(true));
+
+    $action = null;
     if (!$project->isUserMember($viewer->getPHID())) {
       $can_join = PhabricatorPolicyFilter::hasCapability(
         $viewer,
@@ -164,7 +186,9 @@ final class SprintProjectProfileController
         ->setName('#'.$slug->getSlug());
     }
 
-    $view->addProperty(pht('Hashtags'), phutil_implode_html(' ', $hashtags));
+    if ($hashtags) {
+      $view->addProperty(pht('Hashtags'), phutil_implode_html(' ', $hashtags));
+    }
 
     $view->addProperty(
       pht('Members'),
diff --git a/src/controller/board/SprintBoardColumnDetailController.php b/src/controller/board/SprintBoardColumnDetailController.php
index 6f3bfc5a9f9b189290b087ecc10629147d87af67..9e59ecfae2fbe0105ec981ffa236bf4195b70e53 100644
--- a/src/controller/board/SprintBoardColumnDetailController.php
+++ b/src/controller/board/SprintBoardColumnDetailController.php
@@ -50,15 +50,16 @@ final class SprintBoardColumnDetailController
       ->setHeader($header)
       ->addPropertyList($properties);
 
-    $nav = $this->buildIconNavView($project);
-    $nav->appendChild($box);
-    $nav->appendChild($timeline);
-
-    return $this->buildApplicationPage(
-        $nav,
-      array(
-        'title' => $title,
-      ));
+    $nav = $this->getProfileMenu();
+
+    return $this->newPage()
+        ->setTitle($title)
+        ->setNavigation($nav)
+        ->appendChild(
+            array(
+                $box,
+                $timeline,
+            ));
   }
 
   private function buildHeaderView(PhabricatorProjectColumn $column) {
diff --git a/src/controller/board/SprintBoardColumnEditController.php b/src/controller/board/SprintBoardColumnEditController.php
index afd2ea58180f93bd66db2e90738bd3aa47a0b4e5..3c79119f41be4de79bb7526dc8f2ee624238ad43 100644
--- a/src/controller/board/SprintBoardColumnEditController.php
+++ b/src/controller/board/SprintBoardColumnEditController.php
@@ -144,13 +144,11 @@ final class SprintBoardColumnEditController
       ->setValidationException($validation_exception)
       ->setForm($form);
 
-    $nav = $this->buildIconNavView($project);
-    $nav->appendChild($form_box);
-
-    return $this->buildApplicationPage(
-      $nav,
-      array(
-        'title' => $title,
-      ));
+    $nav = $this->getProfileMenu();
+
+    return $this->newPage()
+        ->setTitle($title)
+        ->setNavigation($nav)
+        ->appendChild($form_box);
   }
 }
diff --git a/src/controller/board/SprintBoardController.php b/src/controller/board/SprintBoardController.php
index 423a8423b2cff37d609f22712f4d7970ff94b42b..7fd1809f0ab62b8bafaf6f19b59384c6700afea4 100644
--- a/src/controller/board/SprintBoardController.php
+++ b/src/controller/board/SprintBoardController.php
@@ -1,7 +1,7 @@
 <?php
 
 abstract class SprintBoardController
-  extends SprintController {
+  extends SprintProjectController {
 
   private $project;
 
@@ -13,11 +13,12 @@ abstract class SprintBoardController
     return $this->project;
   }
 
-  public function buildIconNavView(PhabricatorProject $project) {
-        $id = $project->getID();
-        $nav = parent::buildIconNavView($project);
-        $nav->selectFilter("board/{$id}/");
-        $nav->addClass('project-board-nav');
-        return $nav;
+  protected function getProfileMenu() {
+    $menu = parent::getProfileMenu();
+
+    $menu->selectFilter(PhabricatorProject::PANEL_WORKBOARD);
+    $menu->addClass('project-board-nav');
+
+    return $menu;
   }
 }
diff --git a/src/controller/board/SprintBoardViewController.php b/src/controller/board/SprintBoardViewController.php
index 76a741dcb73c1552cf1e2e672690bf6cf4e58eca..7b4f7574ed79f829de435b315073d1085fbf5ba1 100755
--- a/src/controller/board/SprintBoardViewController.php
+++ b/src/controller/board/SprintBoardViewController.php
@@ -69,6 +69,13 @@ final class SprintBoardViewController
     // TODO: Expand the checks here if we add the ability
     // to hide the Backlog column
     if (!$columns) {
+      $can_edit = PhabricatorPolicyFilter::hasCapability(
+          $viewer,
+          $project,
+          PhabricatorPolicyCapability::CAN_EDIT);
+      if (!$can_edit) {
+        return $this->noAccessDialog($project);
+      }
       switch ($request->getStr('initialize-type')) {
         case 'backlog-only':
           $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
@@ -409,17 +416,22 @@ final class SprintBoardViewController
       ->appendChild($board)
       ->addClass('project-board-wrapper');
 
-    $nav = $this->buildIconNavView($project);
-    $nav->appendChild($header_box);
-    $nav->appendChild($board_box);
-
-    return $this->buildApplicationPage(
-      $nav,
-      array(
-        'title' => pht('%s Board', $project->getName()),
-        'showFooter' => false,
-        'pageObjects' => array($project->getPHID()),
-      ));
+    $nav = $this->getProfileMenu();
+
+    return $this->newPage()
+        ->setTitle(pht('%s Board', $project->getName()))
+        ->setPageObjectPHIDs(array($project->getPHID()))
+        ->setShowFooter(false)
+        ->setNavigation($nav)
+        ->addQuicksandConfig(
+            array(
+                'boardConfig' => $behavior_config,
+            ))
+        ->appendChild(
+            array(
+                $header_box,
+                $board_box,
+            ));
   }
 
   private function buildSortMenu(
diff --git a/src/engine/SprintProjectDetailsProfilePanel.php b/src/engine/SprintProjectDetailsProfilePanel.php
new file mode 100644
index 0000000000000000000000000000000000000000..a468e56cdef1586665f6a68eedee68a1ac0e7926
--- /dev/null
+++ b/src/engine/SprintProjectDetailsProfilePanel.php
@@ -0,0 +1,59 @@
+<?php
+
+final class SprintProjectDetailsProfilePanel
+    extends PhabricatorProfilePanel {
+
+  const PANELKEY = 'sprint.details';
+
+  public function getPanelTypeName() {
+    return pht('Sprint Details');
+  }
+
+  private function getDefaultName() {
+    return pht('Sprint Details');
+  }
+
+  public function getDisplayName(
+      PhabricatorProfilePanelConfiguration $config) {
+    $name = $config->getPanelProperty('name');
+
+    if (strlen($name)) {
+      return $name;
+    }
+
+    return $this->getDefaultName();
+  }
+
+  public function buildEditEngineFields(
+      PhabricatorProfilePanelConfiguration $config) {
+    return array(
+        id(new PhabricatorTextEditField())
+            ->setKey('name')
+            ->setLabel(pht('Name'))
+            ->setPlaceholder($this->getDefaultName())
+            ->setValue($config->getPanelProperty('name')),
+    );
+  }
+
+  protected function newNavigationMenuItems(
+      PhabricatorProfilePanelConfiguration $config) {
+
+    $project = $config->getProfileObject();
+
+    $id = $project->getID();
+    $picture = $project->getProfileImageURI();
+    $name = $project->getName();
+
+    $href = "/project/sprint/profile/{$id}/";
+
+    $item = $this->newItem()
+        ->setHref($href)
+        ->setName($name)
+        ->setProfileImage($picture);
+
+    return array(
+        $item,
+    );
+  }
+
+}
diff --git a/src/engine/SprintProjectProfilePanelEngine.php b/src/engine/SprintProjectProfilePanelEngine.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff191c5585bd1300853bc45f246d236866a35fd1
--- /dev/null
+++ b/src/engine/SprintProjectProfilePanelEngine.php
@@ -0,0 +1,52 @@
+<?php
+
+final class SprintProjectProfilePanelEngine
+    extends PhabricatorProfilePanelEngine {
+
+  protected function getPanelURI($path) {
+    $project = $this->getProfileObject();
+    $id = $project->getID();
+    return "/project/{$id}/panel/{$path}";
+  }
+
+  protected function getBuiltinProfilePanels($object) {
+    $panels = array();
+
+    $panels[] = $this->newPanel()
+        ->setBuiltinKey(PhabricatorProject::PANEL_PROFILE)
+        ->setPanelKey(SprintProjectDetailsProfilePanel::PANELKEY);
+
+    $panels[] = $this->newPanel()
+        ->setBuiltinKey(PhabricatorProject::PANEL_WORKBOARD)
+        ->setPanelKey(SprintProjectWorkboardProfilePanel::PANELKEY);
+
+    $id = $object->getID();
+    // TODO: This is temporary.
+    $uri = urisprintf(
+        '/maniphest/?statuses=open()&projects=%s#R',
+        $object->getPHID());
+
+    $panels[] = $this->newPanel()
+        ->setBuiltinKey('tasks')
+        ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
+        ->setPanelProperty('icon', 'maniphest')
+        ->setPanelProperty('name', pht('Open Tasks'))
+        ->setPanelProperty('uri', $uri);
+
+    // TODO: This is temporary.
+
+    $panels[] = $this->newPanel()
+        ->setBuiltinKey('feed')
+        ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
+        ->setPanelProperty('icon', 'feed')
+        ->setPanelProperty('name', pht('Feed'))
+        ->setPanelProperty('uri', "/project/feed/{$id}/");
+
+    $panels[] = $this->newPanel()
+        ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS)
+        ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY);
+
+    return $panels;
+  }
+
+}
diff --git a/src/profilepanel/SprintProjectWorkboardProfilePanel.php b/src/profilepanel/SprintProjectWorkboardProfilePanel.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1a8a1e429f93ef481c520b2d8a5ecb7d0964958
--- /dev/null
+++ b/src/profilepanel/SprintProjectWorkboardProfilePanel.php
@@ -0,0 +1,74 @@
+<?php
+
+final class SprintProjectWorkboardProfilePanel
+    extends PhabricatorProfilePanel {
+
+  const PANELKEY = 'sprint.workboard';
+
+  public function getPanelTypeName() {
+    return pht('Project Workboard');
+  }
+
+  private function getDefaultName() {
+    return pht('Workboard');
+  }
+
+  public function getDisplayName(
+      PhabricatorProfilePanelConfiguration $config) {
+    $name = $config->getPanelProperty('name');
+
+    if (strlen($name)) {
+      return $name;
+    }
+
+    return $this->getDefaultName();
+  }
+
+  public function buildEditEngineFields(
+      PhabricatorProfilePanelConfiguration $config) {
+    return array(
+        id(new PhabricatorTextEditField())
+            ->setKey('name')
+            ->setLabel(pht('Name'))
+            ->setPlaceholder($this->getDefaultName())
+            ->setValue($config->getPanelProperty('name')),
+    );
+  }
+
+  protected function newNavigationMenuItems(
+      PhabricatorProfilePanelConfiguration $config) {
+    $viewer = $this->getViewer();
+
+    // Workboards are only available if Maniphest is installed.
+    $class = 'PhabricatorManiphestApplication';
+    if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
+      return array();
+    }
+
+    $project = $config->getProfileObject();
+
+    $columns = id(new PhabricatorProjectColumnQuery())
+        ->setViewer($viewer)
+        ->withProjectPHIDs(array($project->getPHID()))
+        ->execute();
+    if ($columns) {
+      $icon = 'fa-columns';
+    } else {
+      $icon = 'fa-columns grey';
+    }
+
+    $id = $project->getID();
+    $href = "/project/sprint/board/{$id}/";
+    $name = $this->getDisplayName($config);
+
+    $item = $this->newItem()
+        ->setHref($href)
+        ->setName($name)
+        ->setIcon($icon);
+
+    return array(
+        $item,
+    );
+  }
+
+}