diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php
index 9c9d123..85aa4a7 100644
--- a/core/includes/entity.api.php
+++ b/core/includes/entity.api.php
@@ -535,3 +535,91 @@ function hook_entity_field_info_alter(&$info, $entity_type) {
     $info['definitions']['mymodule_text']['class'] = '\Drupal\anothermodule\EntityComputedText';
   }
 }
+
+/**
+ * Act on view modes when loaded.
+ *
+ * @param array $entities
+ *   The view modes keyed by name.
+ */
+function hook_view_mode_load($entities) {
+  foreach ($entities as $entity) {
+    $entity->foo = mymodule_add_something($entity);
+  }
+}
+
+/**
+ * Act on an view mode before it is about to be created or updated.
+ *
+ * @param Drupal\Core\Entity\EntityInterface $entity
+ *   The view mode object.
+ */
+function hook_view_mode_presave(Drupal\Core\Entity\EntityInterface $entity) {
+  entity_info_cache_clear();
+  state()->set('menu_rebuild_needed', TRUE);
+}
+
+/**
+ * Act on view modes when inserted.
+ *
+ * @param Drupal\Core\Entity\EntityInterface $entity
+ *   The view mode object.
+ */
+function hook_view_mode_insert(Drupal\Core\Entity\EntityInterface $entity) {
+  // Insert the new view mode into a fictional table of all view modes.
+  db_insert('example_view_mode')
+    ->fields(array(
+      'type' => $entity->entityType(),
+      'id' => $entity->id(),
+      'created' => REQUEST_TIME,
+      'updated' => REQUEST_TIME,
+    ))
+    ->execute();
+}
+
+/**
+ * Act on view modes when updated.
+ *
+ * @param Drupal\Core\Entity\EntityInterface $entity
+ *   The view mode object.
+ */
+function hook_view_mode_update(Drupal\Core\Entity\EntityInterface $entity) {
+  // Update the view mode's entry in a fictional table of all view modes.
+  db_update('example_view_mode')
+    ->fields(array(
+      'updated' => REQUEST_TIME,
+    ))
+    ->condition('type', $entity->entityType())
+    ->condition('id', $entity->id())
+    ->execute();
+}
+
+/**
+ * Act before view mode deletion.
+ *
+ * @param Drupal\Core\Entity\EntityInterface $entity
+ *   The view mode object for the view mode that is about to be deleted.
+ */
+function hook_view_mode_predelete(Drupal\Core\Entity\EntityInterface $entity) {
+  // Count references to this view mode in a custom table before they are
+  // removed upon view mode deletion.
+  $id = $entity->id();
+  $type = $entity->entityType();
+  $count = db_select('example_view_mode_data')
+    ->condition('type', $type)
+    ->condition('id', $id)
+    ->countQuery()
+    ->execute()
+    ->fetchField();
+}
+
+/**
+ * Respond to view mode deletion.
+ *
+ * @param Drupal\Core\Entity\EntityInterface $entity
+ *   The view mode object for the view mode that has been deleted.
+ */
+function hook_view_mode_delete(Drupal\Core\Entity\EntityInterface $entity) {
+  entity_info_cache_clear();
+  state()->set('menu_rebuild_needed', TRUE);
+}
diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 75c3386..639c53d 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -82,6 +82,20 @@ function entity_get_info($entity_type = NULL) {
           }
         }
       }
+
+      // Add view modes.
+      $view_modes = drupal_container()->get('config.storage')->listAll('view_mode.');
+      foreach ($view_modes as $config_name) {
+        $view_mode = config($config_name)->get();
+        $definition = array(
+          'label' => check_plain($view_mode['label']),
+          'custom settings' => FALSE,
+        );
+        foreach (array_filter($view_mode['entityTypes']) as $key => $value) {
+          $entity_info[$key]['view modes'][$view_mode['name']] = $definition;
+        }
+      }
+
       // Let other modules alter the entity info.
       drupal_alter('entity_info', $entity_info);
       cache()->set("entity_info:$langcode", $entity_info, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
diff --git a/core/lib/Drupal/Core/Entity/EntityViewMode.php b/core/lib/Drupal/Core/Entity/EntityViewMode.php
new file mode 100644
index 0000000..564c1ea
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/EntityViewMode.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Entity\EntityViewMode.
+ */
+
+namespace Drupal\Core\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+
+/**
+ * Defines the view mode configuration entity class.
+ */
+class EntityViewMode extends ConfigEntityBase {
+
+  /**
+   * The name of the view mode.
+   *
+   * @var string
+   */
+  public $name;
+
+  /**
+   * The UUID of the view mode.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The view mode label.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * An array of entity types that use this view mode.
+   *
+   * The array is keyed by the entity type, and the value is either the entity
+   * type if this view mode is used, or 0 if it is not.
+   *
+   * @var array
+   */
+  public $entityTypes = array();
+
+  /**
+   * Overrides Drupal\Core\Core\Entity\Entity::id().
+   */
+  public function id() {
+    return $this->name;
+  }
+
+  /**
+   * Overrides Drupal\Core\Core\Entity\Entity::uri().
+   */
+  public function uri() {
+    return array(
+      'path' => 'admin/config/system/view-modes/' . $this->id(),
+      'options' => array(
+        'entity_type' => $this->entityType,
+        'entity' => $this,
+      ),
+    );
+  }
+
+  /**
+   * Returns the entity types that are used by the view mode.
+   *
+   * @return array
+   *   An array where both keys and values are entity types for the view mode.
+   */
+  public function getUsedEntityTypes() {
+    return array_filter($this->entityTypes);
+  }
+
+}
diff --git a/core/modules/entity_ui/entity_ui.admin.inc b/core/modules/entity_ui/entity_ui.admin.inc
new file mode 100644
index 0000000..8b55c90
--- /dev/null
+++ b/core/modules/entity_ui/entity_ui.admin.inc
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Administrative functions for custom view modes.
+ */
+
+/**
+ * Menu callback: list all view modes.
+ */
+function view_mode_list() {
+  return entity_list_controller('view_mode')->render();
+}
+
+/**
+ * Menu callback: view mode edit form.
+ */
+function view_mode_add() {
+  $view_mode = entity_create('view_mode', array());
+  return entity_get_form($view_mode);
+}
+
+/**
+ * Menu callback: view mode delete confirm form.
+ */
+function view_mode_delete_form($form, $form_state, $view_mode) {
+  $form['#view_mode'] = $view_mode;
+
+  $form['name'] = array(
+    '#type' => 'value',
+    '#value' => $view_mode->id(),
+  );
+
+  return confirm_form(
+    $form,
+    t('Are you sure you want to delete the %view-mode view mode?', array(
+      '%view-mode' => $view_mode->label(),
+    )),
+    'admin/config/system/view-modes',
+    t('Deleting a view mode will cause any output still requesting to use that view mode to use the default display settings.'),
+    t('Delete'),
+    t('Cancel')
+  );
+}
+
+/**
+ * Submit handler: delete a view mode.
+ */
+function view_mode_delete_form_submit($form, &$form_state) {
+  drupal_set_message(t('Deleted the %view-mode view mode.', array(
+    '%view-mode' => $form['#view_mode']->label(),
+  )));
+  $form['#view_mode']->delete();
+  $form_state['redirect'] = 'admin/config/system/view-modes';
+}
diff --git a/core/modules/entity_ui/entity_ui.info b/core/modules/entity_ui/entity_ui.info
new file mode 100644
index 0000000..9dcc4e5
--- /dev/null
+++ b/core/modules/entity_ui/entity_ui.info
@@ -0,0 +1,7 @@
+name = Entity UI
+description = User interface for the Entity API.
+package = Core
+version = VERSION
+core = 8.x
+recommends[] = field_ui
+configure = admin/config/system/view-modes
diff --git a/core/modules/entity_ui/entity_ui.module b/core/modules/entity_ui/entity_ui.module
new file mode 100644
index 0000000..5c14354
--- /dev/null
+++ b/core/modules/entity_ui/entity_ui.module
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Provides a user interface for the Entity API.
+ */
+
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Implements hook_permission().
+ */
+function entity_ui_permission() {
+  return array(
+    'administer view modes' => array(
+      'title' => t('Add, edit and delete custom view modes.'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_entity_info_alter().
+ */
+function entity_ui_entity_info_alter(&$entity_info) {
+  // Add a list and form controller for the view mode entity type.
+  $entity_info['view_mode']['list controller class'] = 'Drupal\entity_ui\ViewModeListController';
+  $entity_info['view_mode']['form controller class'] = array(
+    'default' => 'Drupal\entity_ui\ViewModeFormController',
+  );
+}
+
+/**
+ * Implements hook_menu().
+ */
+function entity_ui_menu() {
+  $items['admin/config/system/view-modes'] = array(
+    'title' => 'View modes',
+    'description' => 'Manage custom view modes.',
+    'page callback' => 'view_mode_list',
+    'access arguments' => array('administer view modes'),
+    'file' => 'entity_ui.admin.inc',
+  );
+  $items['admin/config/system/view-modes/add'] = array(
+    'title' => 'Add view mode',
+    'page callback' => 'view_mode_add',
+    'access arguments' => array('administer view modes'),
+    'file' => 'entity_ui.admin.inc',
+    'type' => MENU_LOCAL_ACTION,
+  );
+  $items['admin/config/system/view-modes/%view_mode/edit'] = array(
+    'title' => 'Edit view mode',
+    'page callback' => 'entity_get_form',
+    'page arguments' => array(4),
+    'access arguments' => array('administer view modes'),
+  );
+  $items['admin/config/system/view-modes/%view_mode/delete'] = array(
+    'title' => 'Delete view mode',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('view_mode_delete_form', 4),
+    'access arguments' => array('administer view modes'),
+    'file' => 'entity_ui.admin.inc',
+  );
+
+  return $items;
+}
+
+/**
+ * Load a custom view mode by machine name.
+ */
+function view_mode_load($machine_name) {
+  return entity_load('view_mode', $machine_name);
+}
+
+/**
+ * Implements hook_view_mode_presave().
+ */
+function entity_ui_view_mode_presave(EntityInterface $entity) {
+  entity_info_cache_clear();
+  state()->set('menu_rebuild_needed', TRUE);
+}
+
+/**
+ * Implements hook_view_mode_delete().
+ */
+function entity_ui_view_mode_delete(EntityInterface $entity) {
+  entity_info_cache_clear();
+  state()->set('menu_rebuild_needed', TRUE);
+}
diff --git a/core/modules/entity_ui/lib/Drupal/entity_ui/Tests/ViewModeTest.php b/core/modules/entity_ui/lib/Drupal/entity_ui/Tests/ViewModeTest.php
new file mode 100644
index 0000000..e369da4
--- /dev/null
+++ b/core/modules/entity_ui/lib/Drupal/entity_ui/Tests/ViewModeTest.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\entity_ui\Tests\ViewModeTest.
+ */
+
+namespace Drupal\entity_ui\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Test managing of view modes.
+ */
+class ViewModeTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('field_ui', 'entity_ui');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'View modes',
+      'description' => 'Tests for managing custom view modes.',
+      'group' => 'Entity UI',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    $this->drupalLogin($this->drupalCreateUser(array('administer content types', 'administer users', 'administer view modes', 'access administration pages')));
+    $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
+  }
+
+  /**
+   * Creates a view mode.
+   *
+   * @param array $edit
+   *   (optional) An array of view mode properties. Defaults to an empty array.
+   */
+  function createViewMode(&$edit = array()) {
+    $edit += array(
+      'label' => 'Testing',
+      'name' => 'testing',
+      'entityTypes[node]' => '1'
+    );
+
+    $this->drupalPost('admin/config/system/view-modes/add', $edit, t('Save'));
+    $this->assertText(format_string('Saved the !name view mode.', array('!name' => $edit['label'])));
+  }
+
+  /**
+   * Test managing view modes.
+   */
+  function testManageViewModes() {
+    $edit = array();
+    $this->createViewMode($edit);
+
+    // Create the same and assert it already exists.
+    $this->drupalPost('admin/config/system/view-modes/add', $edit, t('Save'));
+    $this->assertText('The machine-readable name is already in use. It must be unique.', 'View mode testing already exists.');
+
+    // Assert it's found on the Field UI for article.
+    $this->drupalGet('admin/structure/types/manage/article/display');
+    $this->assertRaw('view_modes_custom[testing]', 'Testing view mode found on node article.');
+
+    // Assert it's not found on the Field UI for user.
+    $this->drupalGet('admin/config/people/accounts/display');
+    $this->assertNoRaw('view_modes_custom[testing]', 'Testing view mode not found on user.');
+
+    // Update view mode label.
+    $edit = array(
+      'label' => 'Testing 2',
+    );
+    $this->drupalPost('admin/config/system/view-modes/testing/edit', $edit, t('Save'));
+    $this->assertText('Saved the Testing 2 view mode.', 'Testing label updated.');
+
+    // Remove a view mode.
+    $this->drupalPost('admin/config/system/view-modes/testing/delete', array(), t('Delete'));
+    $this->assertText('Deleted the Testing 2 view mode', 'Deleted the Testing view mode.');
+
+    // Assert the view mode is gone at the manage display screen.
+    $this->drupalGet('admin/structure/types/manage/article/display');
+    $this->assertNoRaw('view_modes_custom[testing]', 'Testing view mode not found on node article.');
+  }
+
+}
diff --git a/core/modules/entity_ui/lib/Drupal/entity_ui/ViewModeFormController.php b/core/modules/entity_ui/lib/Drupal/entity_ui/ViewModeFormController.php
new file mode 100644
index 0000000..a2e97e2
--- /dev/null
+++ b/core/modules/entity_ui/lib/Drupal/entity_ui/ViewModeFormController.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\entity_ui\ViewModeFormController.
+ */
+
+namespace Drupal\entity_ui;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityFormController;
+
+/**
+ * Form controller for the view mode forms.
+ */
+class ViewModeFormController extends EntityFormController {
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::form().
+   */
+  public function form(array $form, array &$form_state, EntityInterface $view_mode) {
+    $form['label'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Label'),
+      '#default_value' => $view_mode->label,
+      '#required' => TRUE,
+    );
+
+    $form['name'] = array(
+      '#type' => 'machine_name',
+      '#machine_name' => array(
+        'source' => array('label'),
+        'exists' => 'view_mode_load',
+      ),
+      '#default_value' => $view_mode->name,
+      '#disabled' => !empty($view_mode->label),
+    );
+
+    $options = array();
+    $entity_info = entity_get_info();
+    foreach ($entity_info as $entity_type => $info) {
+      if (!empty($info['fieldable'])) {
+        $options[$entity_type] = $info['label'];
+      }
+    }
+
+    $form['entityTypes'] = array(
+      '#required' => TRUE,
+      '#type' => 'checkboxes',
+      '#title' => t('Enable this view mode for the following types'),
+      '#options' => $options,
+      '#default_value' => $view_mode->getUsedEntityTypes(),
+    );
+
+    return $form;
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::save().
+   *
+   * @todo Move this code to the base controller: http://drupal.org/node/1728786
+   */
+  public function save(array $form, array &$form_state) {
+    $view_mode = $this->getEntity($form_state);
+    $view_mode->save();
+    drupal_set_message(t('Saved the %view-mode view mode.', array(
+      '%view-mode' => $view_mode->label(),
+    )));
+
+    $form_state['redirect'] = 'admin/config/system/view-modes';
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::delete().
+   *
+   * @todo Move this code to the base controller: http://drupal.org/node/1728786
+   */
+  public function delete(array $form, array &$form_state) {
+    $destination = array();
+    if (isset($_GET['destination'])) {
+      $destination = drupal_get_destination();
+      unset($_GET['destination']);
+    }
+    $view_mode = $this->getEntity($form_state);
+    $form_state['redirect'] = array('admin/config/system/view-modes/' . $view_mode->id() . '/delete', array('query' => $destination));
+  }
+
+}
diff --git a/core/modules/entity_ui/lib/Drupal/entity_ui/ViewModeListController.php b/core/modules/entity_ui/lib/Drupal/entity_ui/ViewModeListController.php
new file mode 100644
index 0000000..f55f701
--- /dev/null
+++ b/core/modules/entity_ui/lib/Drupal/entity_ui/ViewModeListController.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\entity_ui\ViewModeListController.
+ */
+
+namespace Drupal\entity_ui;
+
+use Drupal\Core\Config\Entity\ConfigEntityListController;
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Provides a listing of view modes.
+ */
+class ViewModeListController extends ConfigEntityListController {
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityListController::buildHeader();
+   */
+  public function buildHeader() {
+    $header = parent::buildHeader();
+    $operations = array_pop($header);
+    $header['entities'] = t('Entities');
+    $header['operations'] = $operations;
+    return $header;
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityListController::buildRow();
+   */
+  public function buildRow(EntityInterface $view_mode) {
+    $row = parent::buildRow($view_mode);
+    $operations = array_pop($row);
+    $entity_types = array();
+    $entity_info = entity_get_info();
+    foreach ($view_mode->getUsedEntityTypes() as $entity_type) {
+      $entity_types[] = $entity_info[$entity_type]['label'];
+    }
+    $row['entities'] = implode(', ', $entity_types);
+    $row['operations'] = $operations;
+    return $row;
+  }
+
+}
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index d1c314d..19afe93 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1079,6 +1079,30 @@ function system_menu() {
 }
 
 /**
+ * Implements hook_entity_info().
+ */
+function system_entity_info() {
+  // This entity type is provided on behalf of the entity system.
+  // @todo Remove from system module after http://drupal.org/node/1763974.
+  $return = array(
+    'view_mode' => array(
+      'label' => t('View mode'),
+      'entity class' => 'Drupal\Core\Entity\EntityViewMode',
+      'controller class' => 'Drupal\Core\Config\Entity\ConfigStorageController',
+      'config prefix' => 'view_mode',
+      'fieldable' => FALSE,
+      'entity keys' => array(
+        'id' => 'name',
+        'label' => 'label',
+        'uuid' => 'uuid',
+      ),
+    ),
+  );
+
+  return $return;
+}
+
+/**
  * Page callback; Execute cron tasks.
  *
  * @see system_cron_access().
