diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 14b7c79664..1ffb93ec11 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1256,6 +1256,7 @@ phutil_register_library_map(array(
     'PhabricatorProjectProfileEditController' => 'applications/project/controller/PhabricatorProjectProfileEditController.php',
     'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php',
     'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php',
+    'PhabricatorProjectTestDataGenerator' => 'applications/project/lipsum/PhabricatorProjectTestDataGenerator.php',
     'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php',
     'PhabricatorProjectTransactionType' => 'applications/project/constants/PhabricatorProjectTransactionType.php',
     'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php',
@@ -2964,6 +2965,7 @@ phutil_register_library_map(array(
     'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
     'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController',
     'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+    'PhabricatorProjectTestDataGenerator' => 'PhabricatorTestDataGenerator',
     'PhabricatorProjectTransaction' => 'PhabricatorProjectDAO',
     'PhabricatorProjectTransactionType' => 'PhabricatorProjectConstants',
     'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
diff --git a/src/applications/phid/PhabricatorObjectHandle.php b/src/applications/phid/PhabricatorObjectHandle.php
index 8c08149624..a7114c856a 100644
--- a/src/applications/phid/PhabricatorObjectHandle.php
+++ b/src/applications/phid/PhabricatorObjectHandle.php
@@ -113,6 +113,7 @@ final class PhabricatorObjectHandle {
       PhabricatorPHIDConstants::PHID_TYPE_QUES => 'Question',
       PhabricatorPHIDConstants::PHID_TYPE_PVAR => 'Variable',
       PhabricatorPHIDConstants::PHID_TYPE_PSTE => 'Paste',
+      PhabricatorPHIDConstants::PHID_TYPE_PROJ => 'Project',
     );
 
     return idx($map, $this->getType(), $this->getType());
diff --git a/src/applications/project/lipsum/PhabricatorProjectTestDataGenerator.php b/src/applications/project/lipsum/PhabricatorProjectTestDataGenerator.php
new file mode 100644
index 0000000000..af726170a8
--- /dev/null
+++ b/src/applications/project/lipsum/PhabricatorProjectTestDataGenerator.php
@@ -0,0 +1,89 @@
+<?php
+
+final class PhabricatorProjectTestDataGenerator
+  extends PhabricatorTestDataGenerator {
+
+  private $xactions = array();
+
+  public function generate() {
+    $title = $this->generateTitle();
+    $author = $this->loadAuthorPHID();
+    $project = id(new PhabricatorProject())
+      ->setName($title)
+      ->setAuthorPHID($author);
+
+    $this->addTransaction(
+      PhabricatorProjectTransactionType::TYPE_NAME,
+      $title);
+    $this->addTransaction(
+      PhabricatorProjectTransactionType::TYPE_MEMBERS,
+      $this->loadMembersWithAuthor($author));
+    $this->addTransaction(
+      PhabricatorProjectTransactionType::TYPE_STATUS,
+      $this->generateProjectStatus());
+    $this->addTransaction(
+      PhabricatorProjectTransactionType::TYPE_CAN_VIEW,
+      PhabricatorPolicies::POLICY_PUBLIC);
+    $this->addTransaction(
+      PhabricatorProjectTransactionType::TYPE_CAN_EDIT,
+      PhabricatorPolicies::POLICY_PUBLIC);
+    $this->addTransaction(
+      PhabricatorProjectTransactionType::TYPE_CAN_JOIN,
+      PhabricatorPolicies::POLICY_PUBLIC);
+
+    $editor = id(new PhabricatorProjectEditor($project))
+      ->setActor(id(new PhabricatorUser())
+          ->loadOneWhere('phid = %s', $author))
+      ->applyTransactions($this->xactions);
+
+    $profile = id(new PhabricatorProjectProfile())
+      ->setBlurb($this->generateDescription())
+      ->setProjectPHID($project->getPHID())
+      ->save();
+
+    return $project->save();
+  }
+
+  private function addTransaction($type, $value) {
+    $this->xactions[] = id(new PhabricatorProjectTransaction())
+      ->setTransactionType($type)
+      ->setNewValue($value);
+  }
+
+  private function loadPhabrictorUserPHID() {
+    return $this->loadOneRandom("PhabricatorUser")->getPHID();
+  }
+
+  public function loadAuthorPHID() {
+    return $this->loadPhabrictorUserPHID();
+  }
+
+  public function loadMembersWithAuthor($author) {
+    $members = array($author);
+    for ($i = 0; $i < rand(10, 20);$i++) {
+      $members[] = $this->loadPhabrictorUserPHID();
+    }
+    return $members;
+  }
+
+  public function generateTitle() {
+    return id(new PhutilLipsumContextFreeGrammar())
+      ->generate();
+  }
+
+  public function generateDescription() {
+    return id(new PhutilLipsumContextFreeGrammar())
+      ->generateSeveral(rand(30, 40));
+  }
+
+  public function generateProjectStatus() {
+    $statuses = array_keys(PhabricatorProjectStatus::getStatusMap());
+    // Make sure 4/5th of all generated Projects are active
+    $random = rand(0, 4);
+    if ($random != 0) {
+      return $statuses[0];
+    } else {
+      return $statuses[1];
+    }
+  }
+}