diff --git a/project/peopledetail.py b/project/peopledetail.py
new file mode 100644
index 0000000..3c4846b
--- /dev/null
+++ b/project/peopledetail.py
@@ -0,0 +1,271 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+"""A class to display details about each project member."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import logging
+import time
+
+import ezt
+
+from framework import exceptions
+from framework import framework_bizobj
+from framework import framework_helpers
+from framework import framework_views
+from framework import jsonfeed
+from framework import permissions
+from framework import servlet
+from framework import template_helpers
+from framework import urls
+from project import project_helpers
+from project import project_views
+
+CHECKBOX_PERMS = [
+    permissions.VIEW,
+    permissions.COMMIT,
+    permissions.CREATE_ISSUE,
+    permissions.ADD_ISSUE_COMMENT,
+    permissions.EDIT_ISSUE,
+    permissions.EDIT_ISSUE_OWNER,
+    permissions.EDIT_ISSUE_SUMMARY,
+    permissions.EDIT_ISSUE_STATUS,
+    permissions.EDIT_ISSUE_CC,
+    permissions.DELETE_ISSUE,
+    permissions.DELETE_OWN,
+    permissions.DELETE_ANY,
+    permissions.EDIT_ANY_MEMBER_NOTES,
+    permissions.MODERATE_SPAM,
+    ]
+
+
+class PeopleDetail(servlet.Servlet):
+  """People detail page documents one partipant's involvement in a project."""
+
+  _PAGE_TEMPLATE = 'project/people-detail-page.ezt'
+  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_PEOPLE
+
+  def AssertBasePermission(self, mr):
+    """Check that the user is allowed to access this servlet."""
+    super(PeopleDetail, self).AssertBasePermission(mr)
+    member_id = self.ValidateMemberID(mr.cnxn, mr.specified_user_id, mr.project)
+    # For now, contributors who cannot view other contributors are further
+    # restricted from viewing any part of the member list or detail pages.
+    if (not permissions.CanViewContributorList(mr, mr.project) and
+        member_id != mr.auth.user_id):
+      raise permissions.PermissionException(
+          'User is not allowed to view other people\'s details')
+
+  def GatherPageData(self, mr):
+    """Build up a dictionary of data values to use when rendering the page."""
+
+    member_id = self.ValidateMemberID(mr.cnxn, mr.specified_user_id, mr.project)
+    group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups(
+        mr.cnxn, [member_id])
+    users_by_id = framework_views.MakeAllUserViews(
+        mr.cnxn, self.services.user, [member_id])
+    framework_views.RevealAllEmailsToMembers(
+        mr.cnxn, self.services, mr.auth, users_by_id, mr.project)
+
+    project_commitments = self.services.project.GetProjectCommitments(
+        mr.cnxn, mr.project_id)
+    (ac_exclusion_ids, no_expand_ids
+     ) = self.services.project.GetProjectAutocompleteExclusion(
+        mr.cnxn, mr.project_id)
+    member_view = project_views.MemberView(
+        mr.auth.user_id, member_id, users_by_id[member_id], mr.project,
+        project_commitments,
+        ac_exclusion=(member_id in ac_exclusion_ids),
+        no_expand=(member_id in no_expand_ids),
+        is_group=(member_id in group_ids))
+
+    member_user = self.services.user.GetUser(mr.cnxn, member_id)
+    # This ignores indirect memberships, which is ok because we are viewing
+    # the page for a member directly involved in the project
+    role_perms = permissions.GetPermissions(
+        member_user, {member_id}, mr.project)
+
+    # TODO(jrobbins): clarify in the UI which permissions are built-in to
+    # the user's direct role, vs. which are granted via a group membership,
+    # vs. which ones are extra_perms that have been added specifically for
+    # this user.
+    member_perms = template_helpers.EZTItem()
+    for perm in CHECKBOX_PERMS:
+      setattr(member_perms, perm,
+              ezt.boolean(role_perms.HasPerm(perm, member_id, mr.project)))
+
+    displayed_extra_perms = [perm for perm in member_view.extra_perms
+                             if perm not in CHECKBOX_PERMS]
+
+    viewing_self = mr.auth.user_id == member_id
+    warn_abandonment = (viewing_self and
+                        permissions.ShouldCheckForAbandonment(mr))
+
+    return {
+        'subtab_mode': None,
+        'member': member_view,
+        'role_perms': role_perms,
+        'member_perms': member_perms,
+        'displayed_extra_perms': displayed_extra_perms,
+        'offer_edit_perms': ezt.boolean(self.CanEditPerms(mr)),
+        'offer_edit_member_notes': ezt.boolean(
+            self.CanEditMemberNotes(mr, member_id)),
+        'offer_remove_role': ezt.boolean(self.CanRemoveRole(mr, member_id)),
+        'expand_perms': ezt.boolean(mr.auth.user_pb.keep_people_perms_open),
+        'warn_abandonment': ezt.boolean(warn_abandonment),
+        'total_num_owners': len(mr.project.owner_ids),
+        }
+
+  def ValidateMemberID(self, cnxn, member_id, project):
+    """Lookup a project member by user_id.
+
+    Args:
+      cnxn: connection to SQL database.
+      member_id: int user_id, same format as user profile page.
+      project: the current Project PB.
+
+    Returns:
+      The user ID of the project member. Raises an exception if the username
+      cannot be looked up, or if that user is not in the project.
+    """
+    if not member_id:
+      self.abort(404, 'project member not specified')
+
+    member_username = None
+    try:
+      member_username = self.services.user.LookupUserEmail(cnxn, member_id)
+    except exceptions.NoSuchUserException:
+      logging.info('user_id %s not found', member_id)
+
+    if not member_username:
+      logging.info('There is no such user id %r', member_id)
+      self.abort(404, 'project member not found')
+
+    if not framework_bizobj.UserIsInProject(project, {member_id}):
+      logging.info('User %r is not a member of %r',
+                   member_username, project.project_name)
+      self.abort(404, 'project member not found')
+
+    return member_id
+
+  def ProcessFormData(self, mr, post_data):
+    """Process the posted form."""
+    # 1. Parse and validate user input.
+    user_id, role, extra_perms, notes, ac_exclusion, no_expand = (
+        self.ParsePersonData(mr, post_data))
+    member_id = self.ValidateMemberID(mr.cnxn, user_id, mr.project)
+
+    # 2. Call services layer to save changes.
+    if 'remove' in post_data:
+      self.ProcessRemove(mr, member_id)
+    else:
+      self.ProcessSave(
+          mr, role, extra_perms, notes, member_id, ac_exclusion, no_expand)
+
+    # 3. Determine the next page in the UI flow.
+    if 'remove' in post_data:
+      return framework_helpers.FormatAbsoluteURL(
+          mr, urls.PEOPLE_LIST, saved=1, ts=int(time.time()))
+    else:
+      return framework_helpers.FormatAbsoluteURL(
+          mr, urls.PEOPLE_DETAIL, u=user_id, saved=1, ts=int(time.time()))
+
+  def ProcessRemove(self, mr, member_id):
+    """Process the posted form when the user pressed 'Remove'."""
+    if not self.CanRemoveRole(mr, member_id):
+      raise permissions.PermissionException(
+          'User is not allowed to remove this member from the project')
+
+    self.RemoveRole(mr.cnxn, mr.project, member_id)
+
+  def ProcessSave(
+      self, mr, role, extra_perms, notes, member_id, ac_exclusion,
+      no_expand):
+    """Process the posted form when the user pressed 'Save'."""
+    if (not self.CanEditPerms(mr) and
+        not self.CanEditMemberNotes(mr, member_id)):
+      raise permissions.PermissionException(
+          'User is not allowed to edit people in this project')
+
+    if self.CanEditPerms(mr):
+      self.services.project.UpdateExtraPerms(
+          mr.cnxn, mr.project_id, member_id, extra_perms)
+      self.UpdateRole(mr.cnxn, mr.project, role, member_id)
+
+    if self.CanEditMemberNotes(mr, member_id):
+      self.services.project.UpdateCommitments(
+          mr.cnxn, mr.project_id, member_id, notes)
+
+    if self.CanEditPerms(mr):
+      self.services.project.UpdateProjectAutocompleteExclusion(
+          mr.cnxn, mr.project_id, member_id, ac_exclusion, no_expand)
+
+  def CanEditMemberNotes(self, mr, member_id):
+    """Return true if the logged in user can edit the current user's notes."""
+    return (self.CheckPerm(mr, permissions.EDIT_ANY_MEMBER_NOTES) or
+            member_id == mr.auth.user_id)
+
+  def CanEditPerms(self, mr):
+    """Return true if the logged in user can edit the current user's perms."""
+    return self.CheckPerm(mr, permissions.EDIT_PROJECT)
+
+  def CanRemoveRole(self, mr, member_id):
+    """Return true if the logged in user can remove the current user's role."""
+    return (self.CheckPerm(mr, permissions.EDIT_PROJECT) or
+            member_id == mr.auth.user_id)
+
+  def ParsePersonData(self, mr, post_data):
+    """Parse the POST data for a project member.
+
+    Args:
+      mr: common information parsed from the user's request.
+      post_data: dictionary of lists of values for each HTML
+          form field.
+
+    Returns:
+      A tuple with user_id, role, extra_perms, and notes.
+    """
+    if not mr.specified_user_id:
+      raise exceptions.InputException('Field user_id is missing')
+
+    role = post_data.get('role', '').lower()
+    extra_perms = []
+    for ep in post_data.getall('extra_perms'):
+      perm = framework_bizobj.CanonicalizeLabel(ep)
+      # Perms with leading underscores are reserved.
+      perm = perm.strip('_')
+      if perm:
+        extra_perms.append(perm)
+
+    notes = post_data.get('notes', '').strip()
+    ac_exclusion = not post_data.get('ac_include', False)
+    no_expand = not post_data.get('ac_expand', False)
+    return (mr.specified_user_id, role, extra_perms, notes, ac_exclusion,
+            no_expand)
+
+  def RemoveRole(self, cnxn, project, member_id):
+    """Remove the given member from the project."""
+    (owner_ids, committer_ids,
+     contributor_ids) = project_helpers.MembersWithoutGivenIDs(
+         project, {member_id})
+    self.services.project.UpdateProjectRoles(
+        cnxn, project.project_id, owner_ids, committer_ids, contributor_ids)
+
+  def UpdateRole(self, cnxn, project, role, member_id):
+    """If the user's role was changed, update that in the Project."""
+    if not role:
+      return  # Role was not in the form data
+
+    if role == framework_helpers.GetRoleName({member_id}, project).lower():
+      return  # No change needed
+
+    (owner_ids, committer_ids,
+     contributor_ids) = project_helpers.MembersWithGivenIDs(
+         project, {member_id}, role)
+
+    self.services.project.UpdateProjectRoles(
+        cnxn, project.project_id, owner_ids, committer_ids, contributor_ids)
