diff --git a/core/modules/layout_builder/config/schema/layout_builder.schema.yml b/core/modules/layout_builder/config/schema/layout_builder.schema.yml
index b870007e33..682caa78c4 100644
--- a/core/modules/layout_builder/config/schema/layout_builder.schema.yml
+++ b/core/modules/layout_builder/config/schema/layout_builder.schema.yml
@@ -5,3 +5,42 @@ core.entity_view_display.*.*.*.third_party.layout_builder:
     allow_custom:
       type: boolean
       label: 'Allow a customized layout'
+    sections:
+      type: sequence
+      sequence:
+        type: layout_builder.section
+
+layout_builder.section:
+  type: mapping
+  label: 'Layout section'
+  mapping:
+    layout_id:
+      type: string
+      label: 'Layout ID'
+    layout_settings:
+      type: layout_plugin.settings.[%parent.layout_id]
+      label: 'Layout settings'
+    components:
+      type: sequence
+      label: 'Components'
+      sequence:
+        type: layout_builder.component
+
+layout_builder.component:
+  type: mapping
+  label: 'Component'
+  mapping:
+    configuration:
+      type: block.settings.[id]
+    region:
+      type: string
+      label: 'Region'
+    uuid:
+      type: uuid
+      label: 'UUID'
+    weight:
+      type: integer
+      label: 'Weight'
+    additional:
+      type: ignore
+      label: 'Additional data'
diff --git a/core/modules/layout_builder/layout_builder.info.yml b/core/modules/layout_builder/layout_builder.info.yml
index e985911464..d4ce72e0ff 100644
--- a/core/modules/layout_builder/layout_builder.info.yml
+++ b/core/modules/layout_builder/layout_builder.info.yml
@@ -7,3 +7,5 @@ core: 8.x
 dependencies:
   - layout_discovery
   - contextual
+  # @todo Discuss removing in https://www.drupal.org/project/drupal/issues/2935999.
+  - field_ui
diff --git a/core/modules/layout_builder/layout_builder.install b/core/modules/layout_builder/layout_builder.install
new file mode 100644
index 0000000000..44001abc8d
--- /dev/null
+++ b/core/modules/layout_builder/layout_builder.install
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains install and update functions for Layout Builder.
+ */
+
+use Drupal\Core\Cache\Cache;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
+use Drupal\layout_builder\Section;
+
+/**
+ * Implements hook_install().
+ */
+function layout_builder_install() {
+  $displays = LayoutBuilderEntityViewDisplay::loadMultiple();
+  /** @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface[] $displays */
+  foreach ($displays as $display) {
+    // Create the first section from any existing Field Layout settings.
+    $field_layout = $display->getThirdPartySettings('field_layout');
+    if (isset($field_layout['id'])) {
+      $field_layout += ['settings' => []];
+      $display->appendSection(new Section($field_layout['id'], $field_layout['settings']));
+    }
+
+    // Sort the components by weight.
+    $components = $display->get('content');
+    uasort($components, 'Drupal\Component\Utility\SortArray::sortByWeightElement');
+    foreach ($components as $name => $component) {
+      $display->setComponent($name, $component);
+    }
+    $display->save();
+  }
+  Cache::invalidateTags(['rendered']);
+}
diff --git a/core/modules/layout_builder/layout_builder.module b/core/modules/layout_builder/layout_builder.module
index 895145d984..80339c1f70 100644
--- a/core/modules/layout_builder/layout_builder.module
+++ b/core/modules/layout_builder/layout_builder.module
@@ -5,17 +5,14 @@
  * Provides hook implementations for Layout Builder.
  */
 
-use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
 use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\Url;
-use Drupal\field\Entity\FieldConfig;
-use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\field\FieldConfigInterface;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplayStorage;
+use Drupal\layout_builder\Form\LayoutBuilderEntityViewDisplayForm;
 
 /**
  * Implements hook_help().
@@ -52,17 +49,18 @@ function layout_builder_entity_type_alter(array &$entity_types) {
       $entity_type->setLinkTemplate('layout-builder', $entity_type->getLinkTemplate('canonical') . '/layout');
     }
   }
+  $entity_types['entity_view_display']
+    ->setClass(LayoutBuilderEntityViewDisplay::class)
+    ->setStorageClass(LayoutBuilderEntityViewDisplayStorage::class)
+    ->setFormClass('edit', LayoutBuilderEntityViewDisplayForm::class);
 }
 
 /**
- * Removes the Layout Builder field both visually and from the #fields handling.
- *
- * This prevents any interaction with this field. It is rendered directly
- * in layout_builder_entity_view_alter().
- *
- * @internal
+ * Implements hook_form_FORM_ID_alter() for \Drupal\field_ui\Form\EntityFormDisplayEditForm.
  */
-function _layout_builder_hide_layout_field(array &$form) {
+function layout_builder_form_entity_form_display_edit_form_alter(&$form, FormStateInterface $form_state) {
+  // Hides the Layout Builder field. It is rendered directly in
+  // \Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay::buildMultiple().
   unset($form['fields']['layout_builder__layout']);
   $key = array_search('layout_builder__layout', $form['#fields']);
   if ($key !== FALSE) {
@@ -71,140 +69,23 @@ function _layout_builder_hide_layout_field(array &$form) {
 }
 
 /**
- * Implements hook_form_FORM_ID_alter() for \Drupal\field_ui\Form\EntityFormDisplayEditForm.
+ * Implements hook_field_config_insert().
  */
-function layout_builder_form_entity_form_display_edit_form_alter(&$form, FormStateInterface $form_state) {
-  _layout_builder_hide_layout_field($form);
+function layout_builder_field_config_insert(FieldConfigInterface $field_config) {
+  // Clear the sample entity for this entity type and bundle.
+  /** @var \Drupal\Core\TempStore\SharedTempStore $tempstore */
+  $tempstore = \Drupal::service('tempstore.shared')->get('layout_builder.sample_entity');
+  $tempstore->delete($field_config->getTargetEntityTypeId() . '.' . $field_config->getTargetBundle());
+  \Drupal::service('plugin.manager.block')->clearCachedDefinitions();
 }
 
 /**
- * Implements hook_form_FORM_ID_alter() for \Drupal\field_ui\Form\EntityViewDisplayEditForm.
+ * Implements hook_field_config_delete().
  */
-function layout_builder_form_entity_view_display_edit_form_alter(&$form, FormStateInterface $form_state) {
-  /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */
-  $display = $form_state->getFormObject()->getEntity();
-  $entity_type = \Drupal::entityTypeManager()->getDefinition($display->getTargetEntityTypeId());
-
-  _layout_builder_hide_layout_field($form);
-
-  // @todo Expand to work for all view modes in
-  //   https://www.drupal.org/node/2907413.
-  if (!in_array($display->getMode(), ['full', 'default'], TRUE)) {
-    return;
-  }
-
-  $form['layout'] = [
-    '#type' => 'details',
-    '#open' => TRUE,
-    '#title' => t('Layout options'),
-    '#tree' => TRUE,
-  ];
-  // @todo Unchecking this box is a destructive action, this should be made
-  //   clear to the user in https://www.drupal.org/node/2914484.
-  $form['layout']['allow_custom'] = [
-    '#type' => 'checkbox',
-    '#title' => t('Allow each @entity to have its layout customized.', [
-      '@entity' => $entity_type->getSingularLabel(),
-    ]),
-    '#default_value' => $display->getThirdPartySetting('layout_builder', 'allow_custom', FALSE),
-  ];
-
-  $form['#entity_builders'][] = 'layout_builder_form_entity_view_display_edit_entity_builder';
-}
-
-/**
- * Entity builder for layout options on the entity view display form.
- *
- * @see layout_builder_form_entity_view_display_edit_form_alter()
- */
-function layout_builder_form_entity_view_display_edit_entity_builder($entity_type_id, EntityViewDisplayInterface $display, &$form, FormStateInterface &$form_state) {
-  $new_value = (bool) $form_state->getValue(['layout', 'allow_custom'], FALSE);
-  $display->setThirdPartySetting('layout_builder', 'allow_custom', $new_value);
-}
-
-/**
- * Implements hook_ENTITY_TYPE_presave().
- */
-function layout_builder_entity_view_display_presave(EntityViewDisplayInterface $display) {
-  $original_value = isset($display->original) ? $display->original->getThirdPartySetting('layout_builder', 'allow_custom', FALSE) : FALSE;
-  $new_value = $display->getThirdPartySetting('layout_builder', 'allow_custom', FALSE);
-  if ($original_value !== $new_value) {
-    $entity_type_id = $display->getTargetEntityTypeId();
-    $bundle = $display->getTargetBundle();
-
-    if ($new_value) {
-      layout_builder_add_layout_section_field($entity_type_id, $bundle);
-    }
-    elseif ($field = FieldConfig::loadByName($entity_type_id, $bundle, 'layout_builder__layout')) {
-      $field->delete();
-    }
-  }
-}
-
-/**
- * Adds a layout section field to a given bundle.
- *
- * @param string $entity_type_id
- *   The entity type ID.
- * @param string $bundle
- *   The bundle.
- * @param string $field_name
- *   (optional) The name for the layout section field. Defaults to
- *   'layout_builder__layout'.
- *
- * @return \Drupal\field\FieldConfigInterface
- *   A layout section field.
- */
-function layout_builder_add_layout_section_field($entity_type_id, $bundle, $field_name = 'layout_builder__layout') {
-  $field = FieldConfig::loadByName($entity_type_id, $bundle, $field_name);
-  if (!$field) {
-    $field_storage = FieldStorageConfig::loadByName($entity_type_id, $field_name);
-    if (!$field_storage) {
-      $field_storage = FieldStorageConfig::create([
-        'entity_type' => $entity_type_id,
-        'field_name' => $field_name,
-        'type' => 'layout_section',
-      ]);
-      $field_storage->save();
-    }
-
-    $field = FieldConfig::create([
-      'field_storage' => $field_storage,
-      'bundle' => $bundle,
-      'label' => t('Layout'),
-    ]);
-    $field->save();
-  }
-  return $field;
-}
-
-/**
- * Implements hook_entity_view_alter().
- */
-function layout_builder_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
-  if ($display->getThirdPartySetting('layout_builder', 'allow_custom', FALSE) && !$entity->layout_builder__layout->isEmpty()) {
-    $contexts = \Drupal::service('context.repository')->getAvailableContexts();
-    // @todo Use EntityContextDefinition after resolving
-    //   https://www.drupal.org/node/2932462.
-    $contexts['layout_builder.entity'] = new Context(new ContextDefinition("entity:{$entity->getEntityTypeId()}", new TranslatableMarkup('@entity being viewed', ['@entity' => $entity->getEntityType()->getLabel()])), $entity);
-    $sections = $entity->layout_builder__layout->getSections();
-    foreach ($sections as $delta => $section) {
-      $build['_layout_builder'][$delta] = $section->toRenderArray($contexts);
-    }
-
-    // If field layout is active, that is all that needs to be removed.
-    if (\Drupal::moduleHandler()->moduleExists('field_layout') && isset($build['_field_layout'])) {
-      unset($build['_field_layout']);
-      return;
-    }
-
-    /** @var \Drupal\Core\Field\FieldDefinitionInterface[] $field_definitions */
-    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($display->getTargetEntityTypeId(), $display->getTargetBundle());
-    // Remove all display-configurable fields.
-    foreach (array_keys($display->getComponents()) as $name) {
-      if ($name !== 'layout_builder__layout' && isset($field_definitions[$name]) && $field_definitions[$name]->isDisplayConfigurable('view')) {
-        unset($build[$name]);
-      }
-    }
-  }
+function layout_builder_field_config_delete(FieldConfigInterface $field_config) {
+  // Clear the sample entity for this entity type and bundle.
+  /** @var \Drupal\Core\TempStore\SharedTempStore $tempstore */
+  $tempstore = \Drupal::service('tempstore.shared')->get('layout_builder.sample_entity');
+  $tempstore->delete($field_config->getTargetEntityTypeId() . '.' . $field_config->getTargetBundle());
+  \Drupal::service('plugin.manager.block')->clearCachedDefinitions();
 }
diff --git a/core/modules/layout_builder/layout_builder.services.yml b/core/modules/layout_builder/layout_builder.services.yml
index db6a1c13b3..38933073d9 100644
--- a/core/modules/layout_builder/layout_builder.services.yml
+++ b/core/modules/layout_builder/layout_builder.services.yml
@@ -9,6 +9,8 @@ services:
   layout_builder.routes:
     class: Drupal\layout_builder\Routing\LayoutBuilderRoutes
     arguments: ['@entity_type.manager', '@entity_field.manager']
+    tags:
+     - { name: event_subscriber }
   layout_builder.route_enhancer:
     class: Drupal\layout_builder\Routing\LayoutBuilderRouteEnhancer
     tags:
@@ -18,6 +20,9 @@ services:
     arguments: ['@layout_builder.tempstore_repository', '@class_resolver']
     tags:
       - { name: paramconverter, priority: 10 }
+  layout_builder.section_storage_param_converter.defaults:
+    class: Drupal\layout_builder\Routing\SectionStorageDefaultsParamConverter
+    arguments: ['@entity.manager']
   layout_builder.section_storage_param_converter.overrides:
     class: Drupal\layout_builder\Routing\SectionStorageOverridesParamConverter
     arguments: ['@entity.manager']
diff --git a/core/modules/layout_builder/src/Cache/LayoutBuilderIsActiveCacheContext.php b/core/modules/layout_builder/src/Cache/LayoutBuilderIsActiveCacheContext.php
index c632f4b33a..3c3bc25c40 100644
--- a/core/modules/layout_builder/src/Cache/LayoutBuilderIsActiveCacheContext.php
+++ b/core/modules/layout_builder/src/Cache/LayoutBuilderIsActiveCacheContext.php
@@ -4,8 +4,8 @@
 
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Cache\Context\CalculatedCacheContextInterface;
-use Drupal\Core\Entity\Entity\EntityViewDisplay;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\layout_builder\OverridesSectionStorageInterface;
 
 /**
  * Determines whether Layout Builder is active for a given entity type or not.
@@ -49,7 +49,7 @@ public function getContext($entity_type_id = NULL) {
     }
 
     $display = $this->getDisplay($entity_type_id);
-    return ($display && $display->getThirdPartySetting('layout_builder', 'allow_custom', FALSE)) ? '1' : '0';
+    return ($display && $display->isOverridable()) ? '1' : '0';
   }
 
   /**
@@ -72,15 +72,15 @@ public function getCacheableMetadata($entity_type_id = NULL) {
    *
    * @param string $entity_type_id
    *   The entity type ID.
-   * @param string $view_mode
-   *   (optional) The view mode that should be used to render the entity.
    *
-   * @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface|null
+   * @return \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface|null
    *   The entity view display, if it exists.
    */
-  protected function getDisplay($entity_type_id, $view_mode = 'full') {
+  protected function getDisplay($entity_type_id) {
     if ($entity = $this->routeMatch->getParameter($entity_type_id)) {
-      return EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
+      if ($entity instanceof OverridesSectionStorageInterface) {
+        return $entity->getDefaultSectionStorage();
+      }
     }
   }
 
diff --git a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php
index 3f3b95e49b..4acf94538f 100644
--- a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php
+++ b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php
@@ -3,11 +3,13 @@
 namespace Drupal\layout_builder\Controller;
 
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Messenger\MessengerInterface;
 use Drupal\Core\Plugin\PluginFormInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Url;
 use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
 use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
+use Drupal\layout_builder\OverridesSectionStorageInterface;
 use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionStorageInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -30,14 +32,24 @@ class LayoutBuilderController implements ContainerInjectionInterface {
    */
   protected $layoutTempstoreRepository;
 
+  /**
+   * The messenger service.
+   *
+   * @var \Drupal\Core\Messenger\MessengerInterface
+   */
+  protected $messenger;
+
   /**
    * LayoutBuilderController constructor.
    *
    * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
    *   The layout tempstore repository.
+   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
+   *   The messenger service.
    */
-  public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository) {
+  public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger) {
     $this->layoutTempstoreRepository = $layout_tempstore_repository;
+    $this->messenger = $messenger;
   }
 
   /**
@@ -45,7 +57,8 @@ public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('layout_builder.tempstore_repository')
+      $container->get('layout_builder.tempstore_repository'),
+      $container->get('messenger')
     );
   }
 
@@ -101,9 +114,16 @@ public function layout(SectionStorageInterface $section_storage, $is_rebuilding
    *   Indicates if the layout is rebuilding.
    */
   protected function prepareLayout(SectionStorageInterface $section_storage, $is_rebuilding) {
-    // For a new layout, begin with a single section of one column.
+    // Only add sections if the layout is new and empty.
     if (!$is_rebuilding && $section_storage->count() === 0) {
       $sections = [];
+      // If this is an empty override, copy the sections from the corresponding
+      // default.
+      if ($section_storage instanceof OverridesSectionStorageInterface) {
+        $sections = $section_storage->getDefaultSectionStorage()->getSections();
+      }
+
+      // For an empty layout, begin with a single section of one column.
       if (!$sections) {
         $sections[] = new Section('layout_onecol');
       }
@@ -277,6 +297,14 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s
   public function saveLayout(SectionStorageInterface $section_storage) {
     $section_storage->save();
     $this->layoutTempstoreRepository->delete($section_storage);
+
+    if ($section_storage instanceof OverridesSectionStorageInterface) {
+      $this->messenger->addMessage($this->t('The layout override has been saved.'));
+    }
+    else {
+      $this->messenger->addMessage($this->t('The layout has been saved.'));
+    }
+
     return new RedirectResponse($section_storage->getCanonicalUrl()->setAbsolute()->toString());
   }
 
@@ -291,7 +319,38 @@ public function saveLayout(SectionStorageInterface $section_storage) {
    */
   public function cancelLayout(SectionStorageInterface $section_storage) {
     $this->layoutTempstoreRepository->delete($section_storage);
+
+    $this->messenger->addMessage($this->t('The changes to the layout have been discarded.'));
+
     return new RedirectResponse($section_storage->getCanonicalUrl()->setAbsolute()->toString());
   }
 
+  /**
+   * Reverts the overridden layout to the defaults.
+   *
+   * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
+   *   The section storage.
+   *
+   * @return \Symfony\Component\HttpFoundation\RedirectResponse
+   *   A redirect response.
+   */
+  public function revertLayout(SectionStorageInterface $section_storage) {
+    if (!$section_storage instanceof OverridesSectionStorageInterface) {
+      throw new \InvalidArgumentException(sprintf('The section storage with type "%s" and ID "%s" does not provide overrides', $section_storage->getStorageType(), $section_storage->getStorageId()));
+    }
+
+    // Remove all sections.
+    while ($section_storage->count()) {
+      $section_storage->removeSection(0);
+    }
+    $section_storage->save();
+    $this->layoutTempstoreRepository->delete($section_storage);
+
+    $this->messenger->addMessage($this->t('The layout has been reverted back to defaults.'));
+
+    // @todo Decide if this is the correct URL to return in
+    //   https://www.drupal.org/project/drupal/issues/2936501.
+    return new RedirectResponse($section_storage->getLayoutBuilderUrl()->setAbsolute()->toString());
+  }
+
 }
diff --git a/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
new file mode 100644
index 0000000000..11d089291c
--- /dev/null
+++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
@@ -0,0 +1,432 @@
+<?php
+
+namespace Drupal\layout_builder\Entity;
+
+use Drupal\Core\Entity\ContentEntityStorageInterface;
+use Drupal\Core\Entity\Entity\EntityViewDisplay as BaseEntityViewDisplay;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\Core\Url;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\layout_builder\Section;
+use Drupal\layout_builder\SectionComponent;
+
+/**
+ * Provides an entity view display entity that has a layout.
+ *
+ * @internal
+ *   Layout Builder is currently experimental and should only be leveraged by
+ *   experimental modules and development releases of contributed modules.
+ *   See https://www.drupal.org/core/experimental for more information.
+ */
+class LayoutBuilderEntityViewDisplay extends BaseEntityViewDisplay implements LayoutEntityDisplayInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isOverridable() {
+    return $this->getThirdPartySetting('layout_builder', 'allow_custom', FALSE);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setOverridable($overridable = TRUE) {
+    $this->setThirdPartySetting('layout_builder', 'allow_custom', $overridable);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSections() {
+    return $this->getThirdPartySetting('layout_builder', 'sections', []);
+  }
+
+  /**
+   * Store the information for all sections.
+   *
+   * @param \Drupal\layout_builder\Section[] $sections
+   *   The sections information.
+   *
+   * @return $this
+   */
+  protected function setSections(array $sections) {
+    $this->setThirdPartySetting('layout_builder', 'sections', array_values($sections));
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function count() {
+    return count($this->getSections());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSection($delta) {
+    if (!$this->hasSection($delta)) {
+      throw new \OutOfBoundsException(sprintf('Invalid delta "%s" for the "%s" entity', $delta, $this->id()));
+    }
+
+    return $this->getSections()[$delta];
+  }
+
+  /**
+   * Sets the section for the given delta on the display.
+   *
+   * @param int $delta
+   *   The delta of the section.
+   * @param \Drupal\layout_builder\Section $section
+   *   The layout section.
+   *
+   * @return $this
+   */
+  protected function setSection($delta, Section $section) {
+    $sections = $this->getSections();
+    $sections[$delta] = $section;
+    $this->setSections($sections);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function appendSection(Section $section) {
+    $delta = $this->count();
+
+    $this->setSection($delta, $section);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function insertSection($delta, Section $section) {
+    if ($this->hasSection($delta)) {
+      $sections = $this->getSections();
+      // @todo Use https://www.drupal.org/node/66183 once resolved.
+      $start = array_slice($sections, 0, $delta);
+      $end = array_slice($sections, $delta);
+      $this->setSections(array_merge($start, [$section], $end));
+    }
+    else {
+      $this->appendSection($section);
+    }
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function removeSection($delta) {
+    $sections = $this->getSections();
+    unset($sections[$delta]);
+    $this->setSections($sections);
+    return $this;
+  }
+
+  /**
+   * Indicates if there is a section at the specified delta.
+   *
+   * @param int $delta
+   *   The delta of the section.
+   *
+   * @return bool
+   *   TRUE if there is a section for this delta, FALSE otherwise.
+   */
+  protected function hasSection($delta) {
+    $sections = $this->getSections();
+    return isset($sections[$delta]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageInterface $storage) {
+    parent::preSave($storage);
+
+    $original_value = isset($this->original) ? $this->original->isOverridable() : FALSE;
+    $new_value = $this->isOverridable();
+    if ($original_value !== $new_value) {
+      $entity_type_id = $this->getTargetEntityTypeId();
+      $bundle = $this->getTargetBundle();
+
+      if ($new_value) {
+        $this->addSectionField($entity_type_id, $bundle, 'layout_builder__layout');
+      }
+      elseif ($field = FieldConfig::loadByName($entity_type_id, $bundle, 'layout_builder__layout')) {
+        $field->delete();
+      }
+    }
+  }
+
+  /**
+   * Adds a layout section field to a given bundle.
+   *
+   * @param string $entity_type_id
+   *   The entity type ID.
+   * @param string $bundle
+   *   The bundle.
+   * @param string $field_name
+   *   The name for the layout section field.
+   */
+  protected function addSectionField($entity_type_id, $bundle, $field_name) {
+    $field = FieldConfig::loadByName($entity_type_id, $bundle, $field_name);
+    if (!$field) {
+      $field_storage = FieldStorageConfig::loadByName($entity_type_id, $field_name);
+      if (!$field_storage) {
+        $field_storage = FieldStorageConfig::create([
+          'entity_type' => $entity_type_id,
+          'field_name' => $field_name,
+          'type' => 'layout_section',
+          'locked' => TRUE,
+        ]);
+        $field_storage->save();
+      }
+
+      $field = FieldConfig::create([
+        'field_storage' => $field_storage,
+        'bundle' => $bundle,
+        'label' => t('Layout'),
+      ]);
+      $field->save();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDefaultRegion() {
+    if (!$this->hasSection(0)) {
+      return parent::getDefaultRegion();
+    }
+
+    $section = $this->getSection(0);
+    return $this->getLayoutDefinition($section->getLayoutId())->getDefaultRegion();
+  }
+
+  /**
+   * Gets a layout definition.
+   *
+   * @param string $layout_id
+   *   The layout ID.
+   *
+   * @return \Drupal\Core\Layout\LayoutDefinition
+   *   The layout definition.
+   */
+  protected function getLayoutDefinition($layout_id) {
+    return $this->layoutPluginManager()->getDefinition($layout_id);
+  }
+
+  /**
+   * Wraps the layout plugin manager.
+   *
+   * @return \Drupal\Core\Layout\LayoutPluginManagerInterface
+   *   The layout plugin manager.
+   */
+  protected function layoutPluginManager() {
+    return \Drupal::service('plugin.manager.core.layout');
+  }
+
+  /**
+   * Wraps the context repository service.
+   *
+   * @return \Drupal\Core\Plugin\Context\ContextRepositoryInterface
+   *   The context repository service.
+   */
+  protected function contextRepository() {
+    return \Drupal::service('context.repository');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildMultiple(array $entities) {
+    $build_list = parent::buildMultiple($entities);
+
+    foreach ($entities as $id => $entity) {
+      $sections = $this->getRuntimeSections($entity);
+      if ($sections) {
+        foreach ($build_list[$id] as $name => $build_part) {
+          $field_definition = $this->getFieldDefinition($name);
+          if ($field_definition && $field_definition->isDisplayConfigurable($this->displayContext)) {
+            unset($build_list[$id][$name]);
+          }
+        }
+
+        // Bypass ::getActiveContexts() in order to use the runtime entity, not
+        // a sample entity.
+        $contexts = $this->contextRepository()->getAvailableContexts();
+        // @todo Use EntityContextDefinition after resolving
+        //   https://www.drupal.org/node/2932462.
+        $contexts['layout_builder.entity'] = new Context(new ContextDefinition("entity:{$entity->getEntityTypeId()}", new TranslatableMarkup('@entity being viewed', ['@entity' => $entity->getEntityType()->getLabel()])), $entity);
+        foreach ($sections as $delta => $section) {
+          $build_list[$id]['_layout_builder'][$delta] = $section->toRenderArray($contexts);
+        }
+      }
+    }
+
+    return $build_list;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContexts() {
+    $entity = $this->getSampleEntity($this->getTargetEntityTypeId(), $this->getTargetBundle());
+    $context_label = new TranslatableMarkup('@entity being viewed', ['@entity' => $entity->getEntityType()->getLabel()]);
+
+    // @todo Use EntityContextDefinition after resolving
+    //   https://www.drupal.org/node/2932462.
+    $contexts = [];
+    $contexts['layout_builder.entity'] = new Context(new ContextDefinition("entity:{$entity->getEntityTypeId()}", $context_label), $entity);
+    return $contexts;
+  }
+
+  /**
+   * Returns a sample entity.
+   *
+   * @param string $entity_type_id
+   *   The entity type ID.
+   * @param string $bundle_id
+   *   The bundle ID.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   *   An entity.
+   */
+  protected function getSampleEntity($entity_type_id, $bundle_id) {
+    /** @var \Drupal\Core\TempStore\SharedTempStore $tempstore */
+    $tempstore = \Drupal::service('tempstore.shared')->get('layout_builder.sample_entity');
+    if ($entity = $tempstore->get("$entity_type_id.$bundle_id")) {
+      return $entity;
+    }
+
+    $entity_storage = $this->entityTypeManager()->getStorage($entity_type_id);
+    if (!$entity_storage instanceof ContentEntityStorageInterface) {
+      throw new \InvalidArgumentException(sprintf('The "%s" entity storage is not supported', $entity_type_id));
+    }
+
+    $entity = $entity_storage->createWithSampleValues($bundle_id);
+    // Mark the sample entity as being a preview.
+    $entity->in_preview = TRUE;
+    $tempstore->set("$entity_type_id.$bundle_id", $entity);
+    return $entity;
+  }
+
+  /**
+   * Gets the runtime sections for a given entity.
+   *
+   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
+   *   The entity.
+   *
+   * @return \Drupal\layout_builder\Section[]
+   *   The sections.
+   */
+  protected function getRuntimeSections(FieldableEntityInterface $entity) {
+    if ($this->isOverridable() && !$entity->get('layout_builder__layout')->isEmpty()) {
+      return $entity->get('layout_builder__layout')->getSections();
+    }
+
+    return $this->getSections();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function label() {
+    $bundle_info = \Drupal::service('entity_type.bundle.info')->getBundleInfo($this->getTargetEntityTypeId());
+    $bundle_label = $bundle_info[$this->getTargetBundle()]['label'];
+    $target_entity_type = $this->entityTypeManager()->getDefinition($this->getTargetEntityTypeId());
+    return new TranslatableMarkup('@bundle @label', ['@bundle' => $bundle_label, '@label' => $target_entity_type->getPluralLabel()]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getStorageType() {
+    return 'defaults';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getStorageId() {
+    return $this->id();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCanonicalUrl() {
+    return Url::fromRoute("entity.entity_view_display.{$this->getTargetEntityTypeId()}.view_mode", $this->getRouteParameters());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLayoutBuilderUrl() {
+    return Url::fromRoute("entity.entity_view_display.{$this->getTargetEntityTypeId()}.layout_builder", $this->getRouteParameters());
+  }
+
+  /**
+   * Returns the route parameters needed to build routes for this entity.
+   *
+   * @return string[]
+   *   An array of route parameters.
+   */
+  protected function getRouteParameters() {
+    $route_parameters = [];
+
+    $entity_type = $this->entityTypeManager()->getDefinition($this->getTargetEntityTypeId());
+    $bundle_parameter_key = $entity_type->getBundleEntityType() ?: 'bundle';
+    $route_parameters[$bundle_parameter_key] = $this->getTargetBundle();
+
+    $route_parameters['view_mode_name'] = $this->getMode();
+    return $route_parameters;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setComponent($name, array $options = []) {
+    parent::setComponent($name, $options);
+
+    // @todo Remove workaround for EntityViewBuilder::getSingleFieldDisplay() in
+    //   https://www.drupal.org/project/drupal/issues/2936464.
+    if ($this->isNew()) {
+      return $this;
+    }
+
+    // Retrieve the updated options after the parent:: call.
+    $options = $this->content[$name];
+    // Provide backwards compatibility by converting to a section component.
+    $field_definition = $this->getFieldDefinition($name);
+    if ($field_definition && $field_definition->isDisplayConfigurable('view') && isset($options['type'])) {
+      if (!$this->hasSection(0)) {
+        $section = new Section('layout_onecol');
+        $this->appendSection($section);
+      }
+      else {
+        $section = $this->getSection(0);
+      }
+
+      $configuration = [];
+      $configuration['id'] = 'field_block:' . $this->getTargetEntityTypeId() . ':' . $name;
+      $configuration['label_display'] = FALSE;
+      $keys = array_flip(['type', 'label', 'settings', 'third_party_settings']);
+      $configuration['formatter'] = array_intersect_key($options, $keys);
+      $configuration['context_mapping']['entity'] = 'layout_builder.entity';
+      $new_component = (new SectionComponent(\Drupal::service('uuid')->generate(), $options['region'], $configuration));
+      $section->appendComponent($new_component);
+    }
+    return $this;
+  }
+
+}
diff --git a/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplayStorage.php b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplayStorage.php
new file mode 100644
index 0000000000..e86df9daf8
--- /dev/null
+++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplayStorage.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Drupal\layout_builder\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityStorage;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\layout_builder\Section;
+use Drupal\layout_builder\SectionComponent;
+
+/**
+ * Provides storage for entity view display entities that have layouts.
+ *
+ * @internal
+ *   Layout Builder is currently experimental and should only be leveraged by
+ *   experimental modules and development releases of contributed modules.
+ *   See https://www.drupal.org/core/experimental for more information.
+ */
+class LayoutBuilderEntityViewDisplayStorage extends ConfigEntityStorage {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function mapToStorageRecord(EntityInterface $entity) {
+    $record = parent::mapToStorageRecord($entity);
+
+    if (!empty($record['third_party_settings']['layout_builder']['sections'])) {
+      $record['third_party_settings']['layout_builder']['sections'] = array_map(function (Section $section) {
+        return $section->toArray();
+      }, $record['third_party_settings']['layout_builder']['sections']);
+    }
+    return $record;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function mapFromStorageRecords(array $records) {
+    foreach ($records as $id => &$record) {
+      if (!empty($record['third_party_settings']['layout_builder']['sections'])) {
+        $sections = &$record['third_party_settings']['layout_builder']['sections'];
+        foreach ($sections as $section_delta => $section) {
+          $sections[$section_delta] = new Section(
+            $section['layout_id'],
+            $section['layout_settings'],
+            array_map(function (array $component) {
+              return (new SectionComponent(
+                $component['uuid'],
+                $component['region'],
+                $component['configuration'],
+                $component['additional']
+              ))->setWeight($component['weight']);
+            }, $section['components'])
+          );
+        }
+      }
+    }
+    return parent::mapFromStorageRecords($records);
+  }
+
+}
diff --git a/core/modules/layout_builder/src/Entity/LayoutEntityDisplayInterface.php b/core/modules/layout_builder/src/Entity/LayoutEntityDisplayInterface.php
new file mode 100644
index 0000000000..1affc53b39
--- /dev/null
+++ b/core/modules/layout_builder/src/Entity/LayoutEntityDisplayInterface.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Drupal\layout_builder\Entity;
+
+use Drupal\Core\Entity\Display\EntityDisplayInterface;
+use Drupal\layout_builder\SectionStorageInterface;
+
+/**
+ * Provides an interface for entity displays that have layout.
+ *
+ * @internal
+ *   Layout Builder is currently experimental and should only be leveraged by
+ *   experimental modules and development releases of contributed modules.
+ *   See https://www.drupal.org/core/experimental for more information.
+ */
+interface LayoutEntityDisplayInterface extends EntityDisplayInterface, SectionStorageInterface {
+
+  /**
+   * Determines if the display allows custom overrides.
+   *
+   * @return bool
+   *   TRUE if custom overrides are allowed, FALSE otherwise.
+   */
+  public function isOverridable();
+
+  /**
+   * Sets the display to allow or disallow overrides.
+   *
+   * @param bool $overridable
+   *   TRUE if the display should allow overrides, FALSE otherwise.
+   *
+   * @return $this
+   */
+  public function setOverridable($overridable = TRUE);
+
+}
diff --git a/core/modules/layout_builder/src/Field/LayoutSectionItemList.php b/core/modules/layout_builder/src/Field/LayoutSectionItemList.php
index 5aabb02828..f67f90eba4 100644
--- a/core/modules/layout_builder/src/Field/LayoutSectionItemList.php
+++ b/core/modules/layout_builder/src/Field/LayoutSectionItemList.php
@@ -6,6 +6,8 @@
 use Drupal\Core\Plugin\Context\Context;
 use Drupal\Core\Plugin\Context\ContextDefinition;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
+use Drupal\layout_builder\OverridesSectionStorageInterface;
 use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionStorageInterface;
 
@@ -16,7 +18,7 @@
  *
  * @see \Drupal\layout_builder\Plugin\Field\FieldType\LayoutSectionItem
  */
-class LayoutSectionItemList extends FieldItemList implements SectionStorageInterface {
+class LayoutSectionItemList extends FieldItemList implements SectionStorageInterface, OverridesSectionStorageInterface {
 
   /**
    * {@inheritdoc}
@@ -27,6 +29,7 @@ public function insertSection($delta, Section $section) {
       $item = $this->createItem($delta);
       $item->section = $section;
 
+      // @todo Use https://www.drupal.org/node/66183 once resolved.
       $start = array_slice($this->list, 0, $delta);
       $end = array_slice($this->list, $delta);
       $this->list = array_merge($start, [$item], $end);
@@ -91,7 +94,7 @@ public function getContexts() {
   /**
    * {@inheritdoc}
    */
-  public function getStorageType() {
+  public static function getStorageType() {
     return 'overrides';
   }
 
@@ -131,6 +134,13 @@ public function getLayoutBuilderUrl() {
     return $this->getEntity()->toUrl('layout-builder');
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefaultSectionStorage() {
+    return LayoutBuilderEntityViewDisplay::collectRenderDisplay($this->getEntity(), 'default');
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/layout_builder/src/Form/AddBlockForm.php b/core/modules/layout_builder/src/Form/AddBlockForm.php
index 83effd6226..14d9646f9e 100644
--- a/core/modules/layout_builder/src/Form/AddBlockForm.php
+++ b/core/modules/layout_builder/src/Form/AddBlockForm.php
@@ -2,8 +2,9 @@
 
 namespace Drupal\layout_builder\Form;
 
-use Drupal\layout_builder\Section;
+use Drupal\Core\Form\FormStateInterface;
 use Drupal\layout_builder\SectionComponent;
+use Drupal\layout_builder\SectionStorageInterface;
 
 /**
  * Provides a form to add a block.
@@ -27,10 +28,28 @@ protected function submitLabel() {
   }
 
   /**
-   * {@inheritdoc}
+   * Builds the form for the block.
+   *
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
+   *   The section storage being configured.
+   * @param int $delta
+   *   The delta of the section.
+   * @param string $region
+   *   The region of the block.
+   * @param string|null $plugin_id
+   *   The plugin ID of the block to add.
+   *
+   * @return array
+   *   The form array.
    */
-  protected function submitBlock(Section $section, $region, $uuid, array $configuration) {
-    $section->appendComponent(new SectionComponent($uuid, $region, $configuration));
+  public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $region = NULL, $plugin_id = NULL) {
+    $component = new SectionComponent($this->uuidGenerator->generate(), $region, ['id' => $plugin_id]);
+    $section_storage->getSection($delta)->appendComponent($component);
+    return $this->doBuildForm($form, $form_state, $section_storage, $delta, $component);
   }
 
 }
diff --git a/core/modules/layout_builder/src/Form/ConfigureBlockFormBase.php b/core/modules/layout_builder/src/Form/ConfigureBlockFormBase.php
index b75e88f083..e1103e9e44 100644
--- a/core/modules/layout_builder/src/Form/ConfigureBlockFormBase.php
+++ b/core/modules/layout_builder/src/Form/ConfigureBlockFormBase.php
@@ -17,7 +17,7 @@
 use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
 use Drupal\layout_builder\Controller\LayoutRebuildTrait;
 use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
-use Drupal\layout_builder\Section;
+use Drupal\layout_builder\SectionComponent;
 use Drupal\layout_builder\SectionStorageInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -59,7 +59,7 @@
    *
    * @var \Drupal\Component\Uuid\UuidInterface
    */
-  protected $uuid;
+  protected $uuidGenerator;
 
   /**
    * The plugin form manager.
@@ -82,6 +82,13 @@
    */
   protected $region;
 
+  /**
+   * The UUID of the component.
+   *
+   * @var string
+   */
+  protected $uuid;
+
   /**
    * The section storage.
    *
@@ -109,7 +116,7 @@ public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore
     $this->layoutTempstoreRepository = $layout_tempstore_repository;
     $this->contextRepository = $context_repository;
     $this->blockManager = $block_manager;
-    $this->uuid = $uuid;
+    $this->uuidGenerator = $uuid;
     $this->classResolver = $class_resolver;
     $this->pluginFormFactory = $plugin_form_manager;
   }
@@ -128,25 +135,6 @@ public static function create(ContainerInterface $container) {
     );
   }
 
-  /**
-   * Prepares the block plugin based on the block ID.
-   *
-   * @param string $block_id
-   *   Either a block ID, or the plugin ID used to create a new block.
-   * @param array $configuration
-   *   The block configuration.
-   *
-   * @return \Drupal\Core\Block\BlockPluginInterface
-   *   The block plugin.
-   */
-  protected function prepareBlock($block_id, array $configuration) {
-    if (!isset($configuration['uuid'])) {
-      $configuration['uuid'] = $this->uuid->generate();
-    }
-
-    return $this->blockManager->createInstance($block_id, $configuration);
-  }
-
   /**
    * Builds the form for the block.
    *
@@ -158,21 +146,17 @@ protected function prepareBlock($block_id, array $configuration) {
    *   The section storage being configured.
    * @param int $delta
    *   The delta of the section.
-   * @param string $region
-   *   The region of the block.
-   * @param string|null $plugin_id
-   *   The plugin ID of the block to add.
-   * @param array $configuration
-   *   (optional) The array of configuration for the block.
+   * @param \Drupal\layout_builder\SectionComponent $component
+   *   The section component containing the block.
    *
    * @return array
    *   The form array.
    */
-  public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $region = NULL, $plugin_id = NULL, array $configuration = []) {
+  public function doBuildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, SectionComponent $component = NULL) {
     $this->sectionStorage = $section_storage;
     $this->delta = $delta;
-    $this->region = $region;
-    $this->block = $this->prepareBlock($plugin_id, $configuration);
+    $this->uuid = $component->getUuid();
+    $this->block = $component->getPlugin();
 
     $form_state->setTemporaryValue('gathered_contexts', $this->getAvailableContexts($section_storage));
 
@@ -204,20 +188,6 @@ public function buildForm(array $form, FormStateInterface $form_state, SectionSt
    */
   abstract protected function submitLabel();
 
-  /**
-   * Handles the submission of a block.
-   *
-   * @param \Drupal\layout_builder\Section $section
-   *   The layout section.
-   * @param string $region
-   *   The region name.
-   * @param string $uuid
-   *   The UUID of the block.
-   * @param array $configuration
-   *   The block configuration.
-   */
-  abstract protected function submitBlock(Section $section, $region, $uuid, array $configuration);
-
   /**
    * {@inheritdoc}
    */
@@ -242,7 +212,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     $configuration = $this->block->getConfiguration();
 
     $section = $this->sectionStorage->getSection($this->delta);
-    $this->submitBlock($section, $this->region, $configuration['uuid'], $configuration);
+    $section->getComponent($this->uuid)->setConfiguration($configuration);
 
     $this->layoutTempstoreRepository->set($this->sectionStorage);
     $form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl());
diff --git a/core/modules/layout_builder/src/Form/LayoutBuilderEntityViewDisplayForm.php b/core/modules/layout_builder/src/Form/LayoutBuilderEntityViewDisplayForm.php
new file mode 100644
index 0000000000..9fa20648ff
--- /dev/null
+++ b/core/modules/layout_builder/src/Form/LayoutBuilderEntityViewDisplayForm.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Drupal\layout_builder\Form;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\field_ui\Form\EntityViewDisplayEditForm;
+use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface;
+
+/**
+ * Edit form for the LayoutBuilderEntityViewDisplay entity type.
+ *
+ * @internal
+ *   Layout Builder is currently experimental and should only be leveraged by
+ *   experimental modules and development releases of contributed modules.
+ *   See https://www.drupal.org/core/experimental for more information.
+ */
+class LayoutBuilderEntityViewDisplayForm extends EntityViewDisplayEditForm {
+
+  /**
+   * The entity being used by this form.
+   *
+   * @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface
+   */
+  protected $entity;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function form(array $form, FormStateInterface $form_state) {
+    $form = parent::form($form, $form_state);
+
+    // Hide the table of fields.
+    $form['fields']['#access'] = FALSE;
+    $form['#fields'] = [];
+    $form['#extra'] = [];
+
+    $form['manage_layout'] = [
+      '#type' => 'link',
+      '#title' => $this->t('Manage layout'),
+      '#weight' => -10,
+      '#attributes' => ['class' => ['button']],
+      '#url' => $this->entity->getLayoutBuilderUrl(),
+    ];
+
+    // @todo Expand to work for all view modes in
+    //   https://www.drupal.org/node/2907413.
+    if ($this->entity->getMode() === 'default') {
+      $form['layout'] = [
+        '#type' => 'details',
+        '#open' => TRUE,
+        '#title' => $this->t('Layout options'),
+        '#tree' => TRUE,
+      ];
+
+      $entity_type = $this->entityTypeManager->getDefinition($this->entity->getTargetEntityTypeId());
+      // @todo Unchecking this box is a destructive action, this should be made
+      //   clear to the user in https://www.drupal.org/node/2914484.
+      $form['layout']['allow_custom'] = [
+        '#type' => 'checkbox',
+        '#title' => $this->t('Allow each @entity to have its layout customized.', [
+          '@entity' => $entity_type->getSingularLabel(),
+        ]),
+        '#default_value' => $this->entity->isOverridable(),
+      ];
+
+      $form['#entity_builders'][] = '::entityFormEntityBuild';
+    }
+    return $form;
+  }
+
+  /**
+   * Entity builder for layout options on the entity view display form.
+   */
+  public function entityFormEntityBuild($entity_type_id, LayoutEntityDisplayInterface $display, &$form, FormStateInterface &$form_state) {
+    $new_value = (bool) $form_state->getValue(['layout', 'allow_custom'], FALSE);
+    $display->setOverridable($new_value);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function buildFieldRow(FieldDefinitionInterface $field_definition, array $form, FormStateInterface $form_state) {
+    // Intentionally empty.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function buildExtraFieldRow($field_id, $extra_field) {
+    // Intentionally empty.
+  }
+
+}
diff --git a/core/modules/layout_builder/src/Form/UpdateBlockForm.php b/core/modules/layout_builder/src/Form/UpdateBlockForm.php
index afca0d25c9..c00b406eb2 100644
--- a/core/modules/layout_builder/src/Form/UpdateBlockForm.php
+++ b/core/modules/layout_builder/src/Form/UpdateBlockForm.php
@@ -2,9 +2,7 @@
 
 namespace Drupal\layout_builder\Form;
 
-use Drupal\Component\Plugin\ConfigurablePluginInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionStorageInterface;
 
 /**
@@ -36,19 +34,13 @@ public function getFormId() {
    *   The region of the block.
    * @param string $uuid
    *   The UUID of the block being updated.
-   * @param array $configuration
-   *   (optional) The array of configuration for the block.
    *
    * @return array
    *   The form array.
    */
-  public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $region = NULL, $uuid = NULL, array $configuration = []) {
-    $plugin = $section_storage->getSection($delta)->getComponent($uuid)->getPlugin();
-    if ($plugin instanceof ConfigurablePluginInterface) {
-      $configuration = $plugin->getConfiguration();
-    }
-
-    return parent::buildForm($form, $form_state, $section_storage, $delta, $region, $plugin->getPluginId(), $configuration);
+  public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $region = NULL, $uuid = NULL) {
+    $component = $section_storage->getSection($delta)->getComponent($uuid);
+    return $this->doBuildForm($form, $form_state, $section_storage, $delta, $component);
   }
 
   /**
@@ -58,11 +50,4 @@ protected function submitLabel() {
     return $this->t('Update');
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function submitBlock(Section $section, $region, $uuid, array $configuration) {
-    $section->getComponent($uuid)->setConfiguration($configuration);
-  }
-
 }
diff --git a/core/modules/layout_builder/src/LayoutTempstoreRepository.php b/core/modules/layout_builder/src/LayoutTempstoreRepository.php
index 0fa9d738bf..39725afc7e 100644
--- a/core/modules/layout_builder/src/LayoutTempstoreRepository.php
+++ b/core/modules/layout_builder/src/LayoutTempstoreRepository.php
@@ -71,7 +71,7 @@ public function delete(SectionStorageInterface $section_storage) {
    *   The tempstore.
    */
   protected function getTempstore(SectionStorageInterface $section_storage) {
-    $collection = 'layout_builder.' . $section_storage->getStorageType();
+    $collection = 'layout_builder.section_storage.' . $section_storage->getStorageType();
     return $this->tempStoreFactory->get($collection);
   }
 
diff --git a/core/modules/layout_builder/src/OverridesSectionStorageInterface.php b/core/modules/layout_builder/src/OverridesSectionStorageInterface.php
new file mode 100644
index 0000000000..0d6fd2b056
--- /dev/null
+++ b/core/modules/layout_builder/src/OverridesSectionStorageInterface.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Drupal\layout_builder;
+
+/**
+ * Defines an interface for an object that stores layout sections for overrides.
+ *
+ * @internal
+ *   Layout Builder is currently experimental and should only be leveraged by
+ *   experimental modules and development releases of contributed modules.
+ *   See https://www.drupal.org/core/experimental for more information.
+ */
+interface OverridesSectionStorageInterface {
+
+  /**
+   * Returns the corresponding defaults section storage for this override.
+   *
+   * @return \Drupal\layout_builder\SectionStorageInterface
+   *   The defaults section storage.
+   *
+   * @todo Determine if this method needs a parameter in
+   *   https://www.drupal.org/project/drupal/issues/2936507.
+   */
+  public function getDefaultSectionStorage();
+
+}
diff --git a/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php b/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php
index 11b3e4588c..0a49465e4b 100644
--- a/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php
+++ b/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php
@@ -17,7 +17,9 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Render\Element;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -130,7 +132,11 @@ protected function getEntity() {
    */
   public function build() {
     $display_settings = $this->getConfiguration()['formatter'];
-    $build = $this->getEntity()->get($this->fieldName)->view($display_settings);
+    $entity = $this->getEntity();
+    $build = $entity->get($this->fieldName)->view($display_settings);
+    if (!empty($entity->in_preview) && !Element::getVisibleChildren($build)) {
+      $build['content']['#markup'] = new TranslatableMarkup('Placeholder for the "@field" field', ['@field' => $this->getFieldDefinition()->getLabel()]);
+    }
     CacheableMetadata::createFromObject($this)->applyTo($build);
     return $build;
   }
diff --git a/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php b/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php
index 0aacc0d052..a0d986bcf1 100644
--- a/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php
+++ b/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php
@@ -12,6 +12,8 @@
 /**
  * Provides local task definitions for the layout builder user interface.
  *
+ * @todo Remove this in https://www.drupal.org/project/drupal/issues/2936655.
+ *
  * @internal
  */
 class LayoutBuilderLocalTaskDeriver extends DeriverBase implements ContainerDeriverInterface {
@@ -48,7 +50,8 @@ public static function create(ContainerInterface $container, $base_plugin_id) {
    * {@inheritdoc}
    */
   public function getDerivativeDefinitions($base_plugin_definition) {
-    foreach (array_keys($this->getEntityTypes()) as $entity_type_id) {
+    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
+      // Overrides.
       $this->derivatives["entity.$entity_type_id.layout_builder"] = $base_plugin_definition + [
         'route_name' => "entity.$entity_type_id.layout_builder",
         'weight' => 15,
@@ -72,6 +75,35 @@ public function getDerivativeDefinitions($base_plugin_definition) {
         'weight' => 5,
         'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id],
       ];
+      $this->derivatives["entity.$entity_type_id.layout_builder_revert"] = $base_plugin_definition + [
+        'route_name' => "entity.$entity_type_id.layout_builder_revert",
+        'title' => $this->t('Revert to defaults'),
+        'parent_id' => "layout_builder_ui:entity.$entity_type_id.layout_builder",
+        'entity_type_id' => $entity_type_id,
+        'weight' => 10,
+        'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id],
+      ];
+
+      // Defaults.
+      $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder"] = $base_plugin_definition + [
+        'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder",
+        'title' => $this->t('Manage layout'),
+        'base_route' => "entity.entity_view_display.$entity_type_id.layout_builder",
+        'entity_type_id' => $entity_type_id,
+      ];
+      $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder_save"] = $base_plugin_definition + [
+        'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder_save",
+        'title' => $this->t('Save Layout'),
+        'parent_id' => "layout_builder_ui:entity.entity_view_display.$entity_type_id.layout_builder",
+        'entity_type_id' => $entity_type_id,
+      ];
+      $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder_cancel"] = $base_plugin_definition + [
+        'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder_cancel",
+        'title' => $this->t('Cancel Layout'),
+        'weight' => 5,
+        'parent_id' => "layout_builder_ui:entity.entity_view_display.$entity_type_id.layout_builder",
+        'entity_type_id' => $entity_type_id,
+      ];
     }
 
     return $this->derivatives;
diff --git a/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php b/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php
index 563021ed57..ace3f93ca6 100644
--- a/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php
+++ b/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php
@@ -5,14 +5,20 @@
 use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Symfony\Component\Routing\Route;
+use Drupal\Core\Routing\RouteBuildEvent;
+use Drupal\Core\Routing\RoutingEvents;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
+use Drupal\layout_builder\Field\LayoutSectionItemList;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Provides routes for the Layout Builder UI.
  *
  * @internal
  */
-class LayoutBuilderRoutes {
+class LayoutBuilderRoutes implements EventSubscriberInterface {
+
+  use LayoutBuilderRoutesTrait;
 
   /**
    * The entity type manager.
@@ -64,68 +70,53 @@ public function getRoutes() {
       $options['parameters'][$entity_type_id]['type'] = 'entity:' . $entity_type_id;
 
       $template = $entity_type->getLinkTemplate('layout-builder');
-      $routes += $this->buildRoute('overrides', 'entity.' . $entity_type_id, $template, $defaults, $requirements, $options);
+      $routes += $this->buildRoute(LayoutSectionItemList::class, 'entity.' . $entity_type_id, $template, $defaults, $requirements, $options);
     }
     return $routes;
   }
 
   /**
-   * Builds the layout routes for the given values.
+   * Alters existing routes for a specific collection.
    *
-   * @param string $type
-   *   The section storage type.
-   * @param string $route_name_prefix
-   *   The prefix to use for the route name.
-   * @param string $path
-   *   The path patten for the routes.
-   * @param array $defaults
-   *   An array of default parameter values.
-   * @param array $requirements
-   *   An array of requirements for parameters.
-   * @param array $options
-   *   An array of options.
-   *
-   * @return \Symfony\Component\Routing\Route[]
-   *   An array of route objects.
+   * @param \Drupal\Core\Routing\RouteBuildEvent $event
+   *   The route build event.
    */
-  protected function buildRoute($type, $route_name_prefix, $path, array $defaults, array $requirements, array $options) {
-    $routes = [];
+  public function onAlterRoutes(RouteBuildEvent $event) {
+    $collection = $event->getRouteCollection();
+    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
+      if ($route_name = $entity_type->get('field_ui_base_route')) {
+        // Try to get the route from the current collection.
+        if (!$entity_route = $collection->get($route_name)) {
+          continue;
+        }
+        $path = $entity_route->getPath() . '/display-layout/{view_mode_name}';
 
-    $defaults['section_storage_type'] = $type;
-    // Provide an empty value to allow the section storage to be upcast.
-    $defaults['section_storage'] = '';
-    // Trigger the layout builder access check.
-    $requirements['_has_layout_section'] = 'true';
-    // Trigger the layout builder RouteEnhancer.
-    $options['_layout_builder'] = TRUE;
+        $defaults = [];
+        $defaults['entity_type_id'] = $entity_type_id;
+        // If the entity type has no bundles and it doesn't use {bundle} in its
+        // admin path, use the entity type.
+        if (strpos($path, '{bundle}') === FALSE) {
+          if (!$entity_type->hasKey('bundle')) {
+            $defaults['bundle'] = $entity_type_id;
+          }
+          else {
+            $defaults['bundle_key'] = $entity_type->getBundleEntityType();
+          }
+        }
 
-    $main_defaults = $defaults;
-    $main_defaults['is_rebuilding'] = FALSE;
-    $main_defaults['_controller'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::layout';
-    $main_defaults['_title_callback'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::title';
-    $route = (new Route($path))
-      ->setDefaults($main_defaults)
-      ->setRequirements($requirements)
-      ->setOptions($options);
-    $routes["{$route_name_prefix}.layout_builder"] = $route;
+        $requirements = [];
+        $requirements['_field_ui_view_mode_access'] = 'administer ' . $entity_type_id . ' display';
 
-    $save_defaults = $defaults;
-    $save_defaults['_controller'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout';
-    $route = (new Route("$path/save"))
-      ->setDefaults($save_defaults)
-      ->setRequirements($requirements)
-      ->setOptions($options);
-    $routes["{$route_name_prefix}.layout_builder_save"] = $route;
+        $options = $entity_route->getOptions();
+        $options['parameters']['section_storage']['layout_builder_tempstore'] = TRUE;
+        $options['_admin_route'] = FALSE;
 
-    $cancel_defaults = $defaults;
-    $cancel_defaults['_controller'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout';
-    $route = (new Route("$path/cancel"))
-      ->setDefaults($cancel_defaults)
-      ->setRequirements($requirements)
-      ->setOptions($options);
-    $routes["{$route_name_prefix}.layout_builder_cancel"] = $route;
-
-    return $routes;
+        $routes = $this->buildRoute(LayoutBuilderEntityViewDisplay::class, 'entity.entity_view_display.' . $entity_type_id, $path, $defaults, $requirements, $options);
+        foreach ($routes as $name => $route) {
+          $collection->add($name, $route);
+        }
+      }
+    }
   }
 
   /**
@@ -154,4 +145,13 @@ protected function getEntityTypes() {
     });
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    // Run after \Drupal\field_ui\Routing\RouteSubscriber.
+    $events[RoutingEvents::ALTER] = ['onAlterRoutes', -110];
+    return $events;
+  }
+
 }
diff --git a/core/modules/layout_builder/src/Routing/LayoutBuilderRoutesTrait.php b/core/modules/layout_builder/src/Routing/LayoutBuilderRoutesTrait.php
new file mode 100644
index 0000000000..920cbcf93e
--- /dev/null
+++ b/core/modules/layout_builder/src/Routing/LayoutBuilderRoutesTrait.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Drupal\layout_builder\Routing;
+
+use Drupal\layout_builder\OverridesSectionStorageInterface;
+use Drupal\layout_builder\SectionStorageInterface;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Provides a trait for building routes for a Layout Builder UI.
+ *
+ * @internal
+ *   Layout Builder is currently experimental and should only be leveraged by
+ *   experimental modules and development releases of contributed modules.
+ *   See https://www.drupal.org/core/experimental for more information.
+ */
+trait LayoutBuilderRoutesTrait {
+
+  /**
+   * Builds the layout routes for the given values.
+   *
+   * @param string $class
+   *   The class defining the section storage.
+   * @param string $route_name_prefix
+   *   The prefix to use for the route name.
+   * @param string $path
+   *   The path patten for the routes.
+   * @param array $defaults
+   *   An array of default parameter values.
+   * @param array $requirements
+   *   An array of requirements for parameters.
+   * @param array $options
+   *   An array of options.
+   *
+   * @return \Symfony\Component\Routing\Route[]
+   *   An array of route objects.
+   */
+  protected function buildRoute($class, $route_name_prefix, $path, array $defaults, array $requirements, array $options) {
+    $routes = [];
+
+    if (!is_subclass_of($class, SectionStorageInterface::class)) {
+      return $routes;
+    }
+
+    $defaults['section_storage_type'] = $class::getStorageType();
+    // Provide an empty value to allow the section storage to be upcast.
+    $defaults['section_storage'] = '';
+    // Trigger the layout builder access check.
+    $requirements['_has_layout_section'] = 'true';
+    // Trigger the layout builder RouteEnhancer.
+    $options['_layout_builder'] = TRUE;
+
+    $main_defaults = $defaults;
+    $main_defaults['is_rebuilding'] = FALSE;
+    $main_defaults['_controller'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::layout';
+    $main_defaults['_title_callback'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::title';
+    $route = (new Route($path))
+      ->setDefaults($main_defaults)
+      ->setRequirements($requirements)
+      ->setOptions($options);
+    $routes["{$route_name_prefix}.layout_builder"] = $route;
+
+    $save_defaults = $defaults;
+    $save_defaults['_controller'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout';
+    $route = (new Route("$path/save"))
+      ->setDefaults($save_defaults)
+      ->setRequirements($requirements)
+      ->setOptions($options);
+    $routes["{$route_name_prefix}.layout_builder_save"] = $route;
+
+    $cancel_defaults = $defaults;
+    $cancel_defaults['_controller'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout';
+    $route = (new Route("$path/cancel"))
+      ->setDefaults($cancel_defaults)
+      ->setRequirements($requirements)
+      ->setOptions($options);
+    $routes["{$route_name_prefix}.layout_builder_cancel"] = $route;
+
+    if (is_subclass_of($class, OverridesSectionStorageInterface::class)) {
+      $revert_defaults = $defaults;
+      $revert_defaults['_controller'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout';
+      $route = (new Route("$path/revert"))
+        ->setDefaults($revert_defaults)
+        ->setRequirements($requirements)
+        ->setOptions($options);
+      $routes["{$route_name_prefix}.layout_builder_revert"] = $route;
+    }
+
+    return $routes;
+  }
+
+}
diff --git a/core/modules/layout_builder/src/Routing/SectionStorageDefaultsParamConverter.php b/core/modules/layout_builder/src/Routing/SectionStorageDefaultsParamConverter.php
new file mode 100644
index 0000000000..c6435786bd
--- /dev/null
+++ b/core/modules/layout_builder/src/Routing/SectionStorageDefaultsParamConverter.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Drupal\layout_builder\Routing;
+
+use Drupal\Core\ParamConverter\EntityConverter;
+
+/**
+ * Provides a param converter for defaults-based section storage.
+ *
+ * @internal
+ *   Layout Builder is currently experimental and should only be leveraged by
+ *   experimental modules and development releases of contributed modules.
+ *   See https://www.drupal.org/core/experimental for more information.
+ */
+class SectionStorageDefaultsParamConverter extends EntityConverter implements SectionStorageParamConverterInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function convert($value, $definition, $name, array $defaults) {
+    if (!$value) {
+      // If a bundle is not provided but a value corresponding to the bundle key
+      // is, use that for the bundle value.
+      if (empty($defaults['bundle']) && isset($defaults['bundle_key']) && !empty($defaults[$defaults['bundle_key']])) {
+        $defaults['bundle'] = $defaults[$defaults['bundle_key']];
+      }
+
+      if (empty($defaults['entity_type_id']) && empty($defaults['bundle']) && empty($defaults['view_mode_name'])) {
+        return NULL;
+      }
+
+      $value = $defaults['entity_type_id'] . '.' . $defaults['bundle'] . '.' . $defaults['view_mode_name'];
+    }
+    return parent::convert($value, $definition, $name, $defaults);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntityTypeFromDefaults($definition, $name, array $defaults) {
+    return 'entity_view_display';
+  }
+
+}
diff --git a/core/modules/layout_builder/src/Section.php b/core/modules/layout_builder/src/Section.php
index 02f274e784..20e9dec579 100644
--- a/core/modules/layout_builder/src/Section.php
+++ b/core/modules/layout_builder/src/Section.php
@@ -307,4 +307,23 @@ protected function layoutPluginManager() {
     return \Drupal::service('plugin.manager.core.layout');
   }
 
+  /**
+   * Returns an array representation of the section.
+   *
+   * @internal
+   *   This is intended for use by a storage mechanism for sections.
+   *
+   * @return array
+   *   An array representation of the section component.
+   */
+  public function toArray() {
+    return [
+      'layout_id' => $this->getLayoutId(),
+      'layout_settings' => $this->getLayoutSettings(),
+      'components' => array_map(function (SectionComponent $component) {
+        return $component->toArray();
+      }, $this->getComponents()),
+    ];
+  }
+
 }
diff --git a/core/modules/layout_builder/src/SectionComponent.php b/core/modules/layout_builder/src/SectionComponent.php
index 6a0c238c70..1f31738d65 100644
--- a/core/modules/layout_builder/src/SectionComponent.php
+++ b/core/modules/layout_builder/src/SectionComponent.php
@@ -306,4 +306,23 @@ protected function currentUser() {
     return \Drupal::currentUser();
   }
 
+  /**
+   * Returns an array representation of the section component.
+   *
+   * @internal
+   *   This is intended for use by a storage mechanism for section components.
+   *
+   * @return array
+   *   An array representation of the section component.
+   */
+  public function toArray() {
+    return [
+      'uuid' => $this->getUuid(),
+      'region' => $this->getRegion(),
+      'configuration' => $this->getConfiguration(),
+      'additional' => $this->additional,
+      'weight' => $this->getWeight(),
+    ];
+  }
+
 }
diff --git a/core/modules/layout_builder/src/SectionStorageInterface.php b/core/modules/layout_builder/src/SectionStorageInterface.php
index 13217d82b4..cc1efaba2a 100644
--- a/core/modules/layout_builder/src/SectionStorageInterface.php
+++ b/core/modules/layout_builder/src/SectionStorageInterface.php
@@ -18,7 +18,7 @@
    * Gets the layout sections.
    *
    * @return \Drupal\layout_builder\Section[]
-   *   An array of sections.
+   *   A sequentially and numerically keyed array of section objects.
    */
   public function getSections();
 
@@ -61,6 +61,9 @@ public function insertSection($delta, Section $section);
   /**
    * Removes the section at the given delta.
    *
+   * As sections are stored sequentially and numerically this will re-key every
+   * subsequent section, shifting them forward.
+   *
    * @param int $delta
    *   The delta of the section.
    *
@@ -92,7 +95,7 @@ public function getStorageId();
    * @return string
    *   The type of storage.
    */
-  public function getStorageType();
+  public static function getStorageType();
 
   /**
    * Gets the label for the object using the sections.
diff --git a/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php b/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php
index b2b5f9c781..99ce2be7df 100644
--- a/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php
+++ b/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php
@@ -2,8 +2,8 @@
 
 namespace Drupal\Tests\layout_builder\Functional;
 
-use Drupal\Core\Entity\Entity\EntityViewDisplay;
 use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
 use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionComponent;
 use Drupal\Tests\BrowserTestBase;
@@ -40,10 +40,9 @@ protected function setUp() {
       'type' => 'bundle_without_section_field',
     ]);
 
-    layout_builder_add_layout_section_field('node', 'bundle_with_section_field');
-    $display = EntityViewDisplay::load('node.bundle_with_section_field.default');
-    $display->setThirdPartySetting('layout_builder', 'allow_custom', TRUE);
-    $display->save();
+    LayoutBuilderEntityViewDisplay::load('node.bundle_with_section_field.default')
+      ->setOverridable()
+      ->save();
 
     $this->drupalLogin($this->drupalCreateUser([
       'configure any layout',
diff --git a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
index 6c376fa7cf..5e405bbca0 100644
--- a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
+++ b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
@@ -42,6 +42,7 @@ protected function setUp() {
 
     $this->installEntitySchema('entity_test_base_field_display');
     $this->installConfig(['filter']);
+    $this->installSchema('system', ['key_value_expire']);
 
     // Set up a non-admin user that is allowed to view test entities.
     \Drupal::currentUser()->setAccount($this->createUser(['uid' => 2], ['view test entity']));
@@ -92,7 +93,7 @@ protected function installLayoutBuilder() {
     $this->refreshServices();
 
     $this->display = $this->reloadEntity($this->display);
-    $this->display->setThirdPartySetting('layout_builder', 'allow_custom', TRUE)->save();
+    $this->display->setOverridable()->save();
     $this->entity = $this->reloadEntity($this->entity);
   }
 
diff --git a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderEntityViewDisplayTest.php b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderEntityViewDisplayTest.php
new file mode 100644
index 0000000000..e0800c06b6
--- /dev/null
+++ b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderEntityViewDisplayTest.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Drupal\Tests\layout_builder\Kernel;
+
+use Drupal\Core\Config\Schema\SchemaIncompleteException;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
+
+/**
+ * @coversDefaultClass \Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay
+ *
+ * @group layout_builder
+ */
+class LayoutBuilderEntityViewDisplayTest extends SectionStorageTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getSectionStorage(array $section_data) {
+    $display = LayoutBuilderEntityViewDisplay::create([
+      'targetEntityType' => 'entity_test',
+      'bundle' => 'entity_test',
+      'mode' => 'default',
+      'status' => TRUE,
+      'third_party_settings' => [
+        'layout_builder' => [
+          'sections' => $section_data,
+        ],
+      ],
+    ]);
+    $display->save();
+    return $display;
+  }
+
+  /**
+   * @covers ::getSection
+   */
+  public function testGetSectionInvalidDelta() {
+    $this->setExpectedException(\OutOfBoundsException::class, 'Invalid delta "2" for the "entity_test.entity_test.default"');
+    $this->sectionStorage->getSection(2);
+  }
+
+  /**
+   * Tests that configuration schema enforces valid values.
+   */
+  public function testInvalidConfiguration() {
+    $this->setExpectedException(SchemaIncompleteException::class);
+    $this->sectionStorage->getSection(0)->getComponent('first-uuid')->setConfiguration(['bar' => 'baz']);
+    $this->sectionStorage->save();
+  }
+
+}
diff --git a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderInstallTest.php b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderInstallTest.php
index 3873af81b0..59ce3535db 100644
--- a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderInstallTest.php
+++ b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderInstallTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\layout_builder\Kernel;
 
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\layout_builder\Section;
 
 /**
@@ -49,6 +51,40 @@ public function testCompatibility() {
     $this->entity->get('layout_builder__layout')->removeSection(0);
     $this->entity->save();
     $this->assertFieldAttributes($this->entity, $expected_fields);
+
+    // Test that adding a new field after Layout Builder has been installed will
+    // add the new field to the default region of the first section.
+    $field_storage = FieldStorageConfig::create([
+      'entity_type' => 'entity_test_base_field_display',
+      'field_name' => 'test_field_display_post_install',
+      'type' => 'text',
+    ]);
+    $field_storage->save();
+    FieldConfig::create([
+      'field_storage' => $field_storage,
+      'bundle' => 'entity_test_base_field_display',
+      'label' => 'FieldConfig with configurable display',
+    ])->save();
+
+    $this->entity = $this->reloadEntity($this->entity);
+    $this->entity->test_field_display_post_install = 'Test string';
+    $this->entity->save();
+
+    $this->display = $this->reloadEntity($this->display);
+    $this->display
+      ->setComponent('test_field_display_post_install', ['region' => 'content', 'weight' => 50])
+      ->save();
+    $new_expected_fields = [
+      'field field--name-name field--type-string field--label-hidden field__item',
+      'field field--name-test-field-display-configurable field--type-boolean field--label-above',
+      'clearfix text-formatted field field--name-test-display-configurable field--type-text field--label-above',
+      'clearfix text-formatted field field--name-test-field-display-post-install field--type-text field--label-above',
+      'clearfix text-formatted field field--name-test-display-non-configurable field--type-text field--label-above',
+      'clearfix text-formatted field field--name-test-display-multiple field--type-text field--label-above',
+    ];
+    $this->assertFieldAttributes($this->entity, $new_expected_fields);
+    $this->assertNotEmpty($this->cssSelect('.layout--onecol'));
+    $this->assertText('Test string');
   }
 
 }
diff --git a/core/modules/layout_builder/tests/src/Kernel/LayoutSectionItemListTest.php b/core/modules/layout_builder/tests/src/Kernel/LayoutSectionItemListTest.php
index f3a6e6f950..af8395f173 100644
--- a/core/modules/layout_builder/tests/src/Kernel/LayoutSectionItemListTest.php
+++ b/core/modules/layout_builder/tests/src/Kernel/LayoutSectionItemListTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\layout_builder\Kernel;
 
 use Drupal\entity_test\Entity\EntityTestBaseFieldDisplay;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
 
 /**
  * Tests the field type for Layout Sections.
@@ -26,7 +27,12 @@ class LayoutSectionItemListTest extends SectionStorageTestBase {
    */
   protected function getSectionStorage(array $section_data) {
     $this->installEntitySchema('entity_test_base_field_display');
-    layout_builder_add_layout_section_field('entity_test_base_field_display', 'entity_test_base_field_display');
+    LayoutBuilderEntityViewDisplay::create([
+      'targetEntityType' => 'entity_test_base_field_display',
+      'bundle' => 'entity_test_base_field_display',
+      'mode' => 'default',
+      'status' => TRUE,
+    ])->setOverridable()->save();
 
     array_map(function ($row) {
       return ['section' => $row];
diff --git a/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php b/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php
index 97c1fba713..173ad90153 100644
--- a/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php
+++ b/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php
@@ -20,6 +20,7 @@
     'layout_test',
     'user',
     'entity_test',
+    'system',
   ];
 
   /**
@@ -35,6 +36,8 @@
   protected function setUp() {
     parent::setUp();
 
+    $this->installSchema('system', ['key_value_expire']);
+
     $section_data = [
       new Section('layout_test_plugin', [], [
         'first-uuid' => new SectionComponent('first-uuid', 'content'),
diff --git a/core/modules/layout_builder/tests/src/Unit/LayoutBuilderRoutesTest.php b/core/modules/layout_builder/tests/src/Unit/LayoutBuilderRoutesTest.php
index e209f6ad43..7eb293bd7a 100644
--- a/core/modules/layout_builder/tests/src/Unit/LayoutBuilderRoutesTest.php
+++ b/core/modules/layout_builder/tests/src/Unit/LayoutBuilderRoutesTest.php
@@ -6,9 +6,11 @@
 use Drupal\Core\Entity\EntityType;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Routing\RouteBuildEvent;
 use Drupal\layout_builder\Routing\LayoutBuilderRoutes;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCollection;
 
 /**
  * @coversDefaultClass \Drupal\layout_builder\Routing\LayoutBuilderRoutes
@@ -146,6 +148,25 @@ public function testGetRoutes() {
           '_layout_builder' => TRUE,
         ]
       ),
+      'entity.with_link_template.layout_builder_revert' => new Route(
+        '/entity/{entity}/layout/revert',
+        [
+          'entity_type_id' => 'with_link_template',
+          'section_storage_type' => 'overrides',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout',
+        ],
+        [
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+            'with_link_template' => ['type' => 'entity:with_link_template'],
+          ],
+          '_layout_builder' => TRUE,
+        ]
+      ),
       'entity.with_integer_id.layout_builder' => new Route(
         '/entity/{entity}/layout',
         [
@@ -208,6 +229,26 @@ public function testGetRoutes() {
           '_layout_builder' => TRUE,
         ]
       ),
+      'entity.with_integer_id.layout_builder_revert' => new Route(
+        '/entity/{entity}/layout/revert',
+        [
+          'entity_type_id' => 'with_integer_id',
+          'section_storage_type' => 'overrides',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout',
+        ],
+        [
+          '_has_layout_section' => 'true',
+          'with_integer_id' => '\d+',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+            'with_integer_id' => ['type' => 'entity:with_integer_id'],
+          ],
+          '_layout_builder' => TRUE,
+        ]
+      ),
       'entity.with_field_ui_route.layout_builder' => new Route(
         '/entity/{entity}/layout',
         [
@@ -270,6 +311,26 @@ public function testGetRoutes() {
           '_layout_builder' => TRUE,
         ]
       ),
+      'entity.with_field_ui_route.layout_builder_revert' => new Route(
+        '/entity/{entity}/layout/revert',
+        [
+          'entity_type_id' => 'with_field_ui_route',
+          'section_storage_type' => 'overrides',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout',
+        ],
+        [
+          '_has_layout_section' => 'true',
+          'with_field_ui_route' => '\d+',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+            'with_field_ui_route' => ['type' => 'entity:with_field_ui_route'],
+          ],
+          '_layout_builder' => TRUE,
+        ]
+      ),
       'entity.with_bundle_key.layout_builder' => new Route(
         '/entity/{entity}/layout',
         [
@@ -332,6 +393,26 @@ public function testGetRoutes() {
           '_layout_builder' => TRUE,
         ]
       ),
+      'entity.with_bundle_key.layout_builder_revert' => new Route(
+        '/entity/{entity}/layout/revert',
+        [
+          'entity_type_id' => 'with_bundle_key',
+          'section_storage_type' => 'overrides',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout',
+        ],
+        [
+          '_has_layout_section' => 'true',
+          'with_bundle_key' => '\d+',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+            'with_bundle_key' => ['type' => 'entity:with_bundle_key'],
+          ],
+          '_layout_builder' => TRUE,
+        ]
+      ),
       'entity.with_bundle_parameter.layout_builder' => new Route(
         '/entity/{entity}/layout',
         [
@@ -394,9 +475,242 @@ public function testGetRoutes() {
           '_layout_builder' => TRUE,
         ]
       ),
+      'entity.with_bundle_parameter.layout_builder_revert' => new Route(
+        '/entity/{entity}/layout/revert',
+        [
+          'entity_type_id' => 'with_bundle_parameter',
+          'section_storage_type' => 'overrides',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout',
+        ],
+        [
+          '_has_layout_section' => 'true',
+          'with_bundle_parameter' => '\d+',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+            'with_bundle_parameter' => ['type' => 'entity:with_bundle_parameter'],
+          ],
+          '_layout_builder' => TRUE,
+        ]
+      ),
     ];
 
     $this->assertEquals($expected, $this->routeBuilder->getRoutes());
   }
 
+  /**
+   * @covers ::onAlterRoutes
+   * @covers ::buildRoute
+   * @covers ::hasIntegerId
+   * @covers ::getEntityTypes
+   */
+  public function testOnAlterRoutes() {
+    $collection = new RouteCollection();
+    $collection->add('known', new Route('/admin/entity/whatever'));
+    $collection->add('with_bundle', new Route('/admin/entity/{bundle}'));
+    $event = new RouteBuildEvent($collection);
+
+    $expected = [
+      'known' => new Route('/admin/entity/whatever'),
+      'with_bundle' => new Route('/admin/entity/{bundle}'),
+      'entity.entity_view_display.with_field_ui_route.layout_builder' => new Route(
+        '/admin/entity/whatever/display-layout/{view_mode_name}',
+        [
+          'entity_type_id' => 'with_field_ui_route',
+          'bundle' => 'with_field_ui_route',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          'is_rebuilding' => FALSE,
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::layout',
+          '_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_field_ui_route display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+      'entity.entity_view_display.with_field_ui_route.layout_builder_save' => new Route(
+        '/admin/entity/whatever/display-layout/{view_mode_name}/save',
+        [
+          'entity_type_id' => 'with_field_ui_route',
+          'bundle' => 'with_field_ui_route',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_field_ui_route display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+      'entity.entity_view_display.with_field_ui_route.layout_builder_cancel' => new Route(
+        '/admin/entity/whatever/display-layout/{view_mode_name}/cancel',
+        [
+          'entity_type_id' => 'with_field_ui_route',
+          'bundle' => 'with_field_ui_route',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_field_ui_route display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+      'entity.entity_view_display.with_bundle_key.layout_builder' => new Route(
+        '/admin/entity/whatever/display-layout/{view_mode_name}',
+        [
+          'entity_type_id' => 'with_bundle_key',
+          'bundle_key' => 'my_bundle_type',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          'is_rebuilding' => FALSE,
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::layout',
+          '_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_bundle_key display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+      'entity.entity_view_display.with_bundle_key.layout_builder_save' => new Route(
+        '/admin/entity/whatever/display-layout/{view_mode_name}/save',
+        [
+          'entity_type_id' => 'with_bundle_key',
+          'bundle_key' => 'my_bundle_type',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_bundle_key display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+      'entity.entity_view_display.with_bundle_key.layout_builder_cancel' => new Route(
+        '/admin/entity/whatever/display-layout/{view_mode_name}/cancel',
+        [
+          'entity_type_id' => 'with_bundle_key',
+          'bundle_key' => 'my_bundle_type',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_bundle_key display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+      'entity.entity_view_display.with_bundle_parameter.layout_builder' => new Route(
+        '/admin/entity/{bundle}/display-layout/{view_mode_name}',
+        [
+          'entity_type_id' => 'with_bundle_parameter',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          'is_rebuilding' => FALSE,
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::layout',
+          '_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_bundle_parameter display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+      'entity.entity_view_display.with_bundle_parameter.layout_builder_save' => new Route(
+        '/admin/entity/{bundle}/display-layout/{view_mode_name}/save',
+        [
+          'entity_type_id' => 'with_bundle_parameter',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_bundle_parameter display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+      'entity.entity_view_display.with_bundle_parameter.layout_builder_cancel' => new Route(
+        '/admin/entity/{bundle}/display-layout/{view_mode_name}/cancel',
+        [
+          'entity_type_id' => 'with_bundle_parameter',
+          'section_storage_type' => 'defaults',
+          'section_storage' => '',
+          '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
+        ],
+        [
+          '_field_ui_view_mode_access' => 'administer with_bundle_parameter display',
+          '_has_layout_section' => 'true',
+        ],
+        [
+          'parameters' => [
+            'section_storage' => ['layout_builder_tempstore' => TRUE],
+          ],
+          '_layout_builder' => TRUE,
+          '_admin_route' => FALSE,
+        ]
+      ),
+    ];
+
+    $this->routeBuilder->onAlterRoutes($event);
+    $this->assertEquals($expected, $event->getRouteCollection()->all());
+  }
+
 }
diff --git a/core/modules/layout_builder/tests/src/Unit/LayoutTempstoreRepositoryTest.php b/core/modules/layout_builder/tests/src/Unit/LayoutTempstoreRepositoryTest.php
index b7702c1184..5d1f691271 100644
--- a/core/modules/layout_builder/tests/src/Unit/LayoutTempstoreRepositoryTest.php
+++ b/core/modules/layout_builder/tests/src/Unit/LayoutTempstoreRepositoryTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\layout_builder\Unit;
 
 use Drupal\layout_builder\LayoutTempstoreRepository;
+use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionStorageInterface;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\TempStore\SharedTempStore;
@@ -18,61 +19,133 @@ class LayoutTempstoreRepositoryTest extends UnitTestCase {
    * @covers ::get
    */
   public function testGetEmptyTempstore() {
-    $section_storage = $this->prophesize(SectionStorageInterface::class);
-    $section_storage->getStorageType()->willReturn('my_storage_type');
-    $section_storage->getStorageId()->willReturn('my_storage_id');
+    $section_storage = new TestSectionStorage();
 
     $tempstore = $this->prophesize(SharedTempStore::class);
     $tempstore->get('my_storage_id')->shouldBeCalled();
 
     $tempstore_factory = $this->prophesize(SharedTempStoreFactory::class);
-    $tempstore_factory->get('layout_builder.my_storage_type')->willReturn($tempstore->reveal());
+    $tempstore_factory->get('layout_builder.section_storage.my_storage_type')->willReturn($tempstore->reveal());
 
     $repository = new LayoutTempstoreRepository($tempstore_factory->reveal());
 
-    $result = $repository->get($section_storage->reveal());
-    $this->assertSame($section_storage->reveal(), $result);
+    $result = $repository->get($section_storage);
+    $this->assertSame($section_storage, $result);
   }
 
   /**
    * @covers ::get
    */
   public function testGetLoadedTempstore() {
-    $section_storage = $this->prophesize(SectionStorageInterface::class);
-    $section_storage->getStorageType()->willReturn('my_storage_type');
-    $section_storage->getStorageId()->willReturn('my_storage_id');
+    $section_storage = new TestSectionStorage();
 
-    $tempstore_section_storage = $this->prophesize(SectionStorageInterface::class);
+    $tempstore_section_storage = new TestSectionStorage();
     $tempstore = $this->prophesize(SharedTempStore::class);
-    $tempstore->get('my_storage_id')->willReturn(['section_storage' => $tempstore_section_storage->reveal()]);
+    $tempstore->get('my_storage_id')->willReturn(['section_storage' => $tempstore_section_storage]);
     $tempstore_factory = $this->prophesize(SharedTempStoreFactory::class);
-    $tempstore_factory->get('layout_builder.my_storage_type')->willReturn($tempstore->reveal());
+    $tempstore_factory->get('layout_builder.section_storage.my_storage_type')->willReturn($tempstore->reveal());
 
     $repository = new LayoutTempstoreRepository($tempstore_factory->reveal());
 
-    $result = $repository->get($section_storage->reveal());
-    $this->assertSame($tempstore_section_storage->reveal(), $result);
-    $this->assertNotSame($section_storage->reveal(), $result);
+    $result = $repository->get($section_storage);
+    $this->assertSame($tempstore_section_storage, $result);
+    $this->assertNotSame($section_storage, $result);
   }
 
   /**
    * @covers ::get
    */
   public function testGetInvalidEntry() {
-    $section_storage = $this->prophesize(SectionStorageInterface::class);
-    $section_storage->getStorageType()->willReturn('my_storage_type');
-    $section_storage->getStorageId()->willReturn('my_storage_id');
+    $section_storage = new TestSectionStorage();
 
     $tempstore = $this->prophesize(SharedTempStore::class);
     $tempstore->get('my_storage_id')->willReturn(['section_storage' => 'this_is_not_an_entity']);
 
     $tempstore_factory = $this->prophesize(SharedTempStoreFactory::class);
-    $tempstore_factory->get('layout_builder.my_storage_type')->willReturn($tempstore->reveal());
+    $tempstore_factory->get('layout_builder.section_storage.my_storage_type')->willReturn($tempstore->reveal());
 
     $repository = new LayoutTempstoreRepository($tempstore_factory->reveal());
 
     $this->setExpectedException(\UnexpectedValueException::class, 'The entry with storage type "my_storage_type" and ID "my_storage_id" is invalid');
-    $repository->get($section_storage->reveal());
+    $repository->get($section_storage);
   }
 
 }
+
+/**
+ * Provides a test implementation of section storage.
+ *
+ * @todo This works around https://github.com/phpspec/prophecy/issues/119.
+ */
+class TestSectionStorage implements SectionStorageInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getStorageType() {
+    return 'my_storage_type';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getStorageId() {
+    return 'my_storage_id';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function count() {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSections() {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSection($delta) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function appendSection(Section $section) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function insertSection($delta, Section $section) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function removeSection($delta) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContexts() {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function label() {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save() {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCanonicalUrl() {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLayoutBuilderUrl() {}
+
+}
diff --git a/core/modules/layout_builder/tests/src/Unit/SectionStorageDefaultsParamConverterTest.php b/core/modules/layout_builder/tests/src/Unit/SectionStorageDefaultsParamConverterTest.php
new file mode 100644
index 0000000000..df07c86cc6
--- /dev/null
+++ b/core/modules/layout_builder/tests/src/Unit/SectionStorageDefaultsParamConverterTest.php
@@ -0,0 +1,111 @@
+<?php
+
+namespace Drupal\Tests\layout_builder\Unit;
+
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityType;
+use Drupal\layout_builder\Routing\SectionStorageDefaultsParamConverter;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\layout_builder\Routing\SectionStorageDefaultsParamConverter
+ *
+ * @group layout_builder
+ */
+class SectionStorageDefaultsParamConverterTest extends UnitTestCase {
+
+  /**
+   * The converter.
+   *
+   * @var \Drupal\layout_builder\Routing\SectionStorageDefaultsParamConverter
+   */
+  protected $converter;
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->entityManager = $this->prophesize(EntityManagerInterface::class);
+    $this->converter = new SectionStorageDefaultsParamConverter($this->entityManager->reveal());
+  }
+
+  /**
+   * @covers ::convert
+   * @covers ::getEntityTypeFromDefaults
+   *
+   * @dataProvider providerTestConvert
+   */
+  public function testConvert($success, $expected_entity_id, $value, array $defaults) {
+    if ($expected_entity_id) {
+      $entity_storage = $this->prophesize(EntityStorageInterface::class);
+      $entity_storage->load($expected_entity_id)->willReturn('the_return_value');
+
+      $this->entityManager->getDefinition('entity_view_display')->willReturn(new EntityType(['id' => 'entity_view_display']));
+      $this->entityManager->getStorage('entity_view_display')->willReturn($entity_storage->reveal());
+    }
+    else {
+      $this->entityManager->getDefinition('entity_view_display')->shouldNotBeCalled();
+      $this->entityManager->getStorage('entity_view_display')->shouldNotBeCalled();
+    }
+
+    $result = $this->converter->convert($value, [], 'the_parameter_name', $defaults);
+    if ($success) {
+      $this->assertEquals('the_return_value', $result);
+    }
+    else {
+      $this->assertNull($result);
+    }
+  }
+
+  /**
+   * Provides data for ::testConvert().
+   */
+  public function providerTestConvert() {
+    $data = [];
+    $data['with value'] = [
+      TRUE,
+      'some_value',
+      'some_value',
+      [],
+    ];
+    $data['empty value, without bundle'] = [
+      TRUE,
+      'my_entity_type.bundle_name.default',
+      '',
+      [
+        'entity_type_id' => 'my_entity_type',
+        'view_mode_name' => 'default',
+        'bundle_key' => 'my_bundle',
+        'my_bundle' => 'bundle_name',
+      ],
+    ];
+    $data['empty value, with bundle'] = [
+      TRUE,
+      'my_entity_type.bundle_name.default',
+      '',
+      [
+        'entity_type_id' => 'my_entity_type',
+        'view_mode_name' => 'default',
+        'bundle' => 'bundle_name',
+      ],
+    ];
+    $data['without value, empty defaults'] = [
+      FALSE,
+      NULL,
+      '',
+      [],
+    ];
+    return $data;
+  }
+
+}
