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.install b/core/modules/layout_builder/layout_builder.install
new file mode 100644
index 0000000000..0982325cc5
--- /dev/null
+++ b/core/modules/layout_builder/layout_builder.install
@@ -0,0 +1,47 @@
+<?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;
+use Drupal\layout_builder\SectionComponent;
+
+/**
+ * Implements hook_install().
+ */
+function layout_builder_install() {
+  $uuid_generator = \Drupal::service('uuid');
+  $entity_field_manager = \Drupal::service('entity_field.manager');
+
+  $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') + [
+      'id' => 'layout_onecol',
+      'settings' => [],
+    ];
+    $components = [];
+    $field_definitions = $entity_field_manager->getFieldDefinitions($display->getTargetEntityTypeId(), $display->getTargetBundle());
+    foreach ($display->getComponents() as $name => $component) {
+      if (isset($field_definitions[$name]) && $field_definitions[$name]->isDisplayConfigurable('view')) {
+        $uuid = $uuid_generator->generate();
+        $configuration = [];
+        $configuration['id'] = 'field_block:' . $display->getTargetEntityTypeId() . ':' . $name;
+        $configuration['formatter']['type'] = $component['type'];
+        $configuration['formatter']['label'] = $component['label'];
+        $configuration['formatter']['settings'] = $component['settings'];
+        $configuration['formatter']['third_party_settings'] = $component['third_party_settings'];
+        $components[] = (new SectionComponent($uuid, $component['region'], $configuration))->setWeight($component['weight']);
+      }
+    }
+    $display
+      ->appendSection(new Section($field_layout['id'], $field_layout['settings'], $components))
+      ->save();
+  }
+  Cache::invalidateTags(['rendered']);
+}
diff --git a/core/modules/layout_builder/layout_builder.module b/core/modules/layout_builder/layout_builder.module
index 0ba9a21f6b..ae08bd6904 100644
--- a/core/modules/layout_builder/layout_builder.module
+++ b/core/modules/layout_builder/layout_builder.module
@@ -5,12 +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\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\field_ui\Form\EntityViewDisplayEditForm;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
+use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplayStorage;
+use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface;
 
 /**
  * Implements hook_help().
@@ -35,13 +37,20 @@ 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);
+  if (\Drupal::moduleHandler()->moduleExists('field_ui')) {
+    // @todo Replace this with a custom UI.
+    $entity_types['entity_view_display']->setFormClass('edit', EntityViewDisplayEditForm::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().
+ * This prevents any interaction with this field. It is rendered directly in
+ * \Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay::buildMultiple().
  *
  * @internal
  */
@@ -64,7 +73,7 @@ function layout_builder_form_entity_form_display_edit_form_alter(&$form, FormSta
  * Implements hook_form_FORM_ID_alter() for \Drupal\field_ui\Form\EntityViewDisplayEditForm.
  */
 function layout_builder_form_entity_view_display_edit_form_alter(&$form, FormStateInterface $form_state) {
-  /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */
+  /** @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface $display */
   $display = $form_state->getFormObject()->getEntity();
   $entity_type = \Drupal::entityTypeManager()->getDefinition($display->getTargetEntityTypeId());
 
@@ -89,7 +98,7 @@ function layout_builder_form_entity_view_display_edit_form_alter(&$form, FormSta
     '#title' => t('Allow each @entity to have its layout customized.', [
       '@entity' => $entity_type->getSingularLabel(),
     ]),
-    '#default_value' => $display->getThirdPartySetting('layout_builder', 'allow_custom', FALSE),
+    '#default_value' => $display->isOverridable(),
   ];
 
   $form['#entity_builders'][] = 'layout_builder_form_entity_view_display_edit_entity_builder';
@@ -100,17 +109,17 @@ function layout_builder_form_entity_view_display_edit_form_alter(&$form, FormSta
  *
  * @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) {
+function layout_builder_form_entity_view_display_edit_entity_builder($entity_type_id, LayoutEntityDisplayInterface $display, &$form, FormStateInterface &$form_state) {
   $new_value = (bool) $form_state->getValue(['layout', 'allow_custom'], FALSE);
-  $display->setThirdPartySetting('layout_builder', 'allow_custom', $new_value);
+  $display->setOverridable($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);
+function layout_builder_entity_view_display_presave(LayoutEntityDisplayInterface $display) {
+  $original_value = isset($display->original) ? $display->original->isOverridable() : FALSE;
+  $new_value = $display->isOverridable();
   if ($original_value !== $new_value) {
     $entity_type_id = $display->getTargetEntityTypeId();
     $bundle = $display->getTargetBundle();
@@ -160,30 +169,3 @@ function layout_builder_add_layout_section_field($entity_type_id, $bundle, $fiel
   }
   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()) {
-    $sections = $entity->layout_builder__layout->getSections();
-    foreach ($sections as $delta => $section) {
-      $build['_layout_builder'][$delta] = $section->toRenderArray();
-    }
-
-    // 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]);
-      }
-    }
-  }
-}
diff --git a/core/modules/layout_builder/layout_builder.services.yml b/core/modules/layout_builder/layout_builder.services.yml
index 67f1aa1b4b..ff07056d8d 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 ff2d17d2ac..a7a4c34297 100644
--- a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php
+++ b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php
@@ -7,6 +7,7 @@
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Url;
 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;
@@ -102,6 +103,13 @@ protected function prepareLayout(SectionStorageInterface $section_storage, $is_r
     // For a new layout, begin with a single section of one column.
     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) {
+        $display = $section_storage->getDefaultSectionStorage();
+        $sections = $display->getSections();
+      }
+
       if (!$sections) {
         $sections[] = new Section('layout_onecol');
       }
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..f5d1d524f7
--- /dev/null
+++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
@@ -0,0 +1,281 @@
+<?php
+
+namespace Drupal\layout_builder\Entity;
+
+use Drupal\Core\Entity\Entity\EntityViewDisplay as BaseEntityViewDisplay;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\layout_builder\Section;
+
+/**
+ * Provides an entity view display entity that has a layout.
+ *
+ * @internal
+ */
+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', $sections);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function count() {
+    return count($this->getSections());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSection($delta) {
+    $sections = $this->getSections();
+    if (!isset($sections[$delta])) {
+      throw new \OutOfBoundsException(sprintf('Invalid delta "%s" for the "%s" entity', $delta, $this->id()));
+    }
+    return $sections[$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) {
+    $sections = $this->getSections();
+    if (isset($sections[$delta])) {
+      $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(array_values($sections));
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function urlRouteParameters($rel) {
+    $route_parameters = parent::urlRouteParameters($rel);
+
+    // @todo Move this to \Drupal\Core\Entity\EntityDisplayBase.
+    $entity_type = $this->entityTypeManager()->getDefinition($this->getTargetEntityTypeId());
+    $bundle_parameter_key = $entity_type->getBundleEntityType() ?: 'bundle';
+    $route_parameters[$bundle_parameter_key] = $this->getTargetBundle();
+    return $route_parameters;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function linkTemplates() {
+    $link_templates = parent::linkTemplates();
+    $link_templates[$this->getTargetEntityTypeId() . '.layout-builder'] = TRUE;
+    return $link_templates;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function toUrl($rel = 'edit-form', array $options = []) {
+    if ($rel === 'canonical') {
+      $rel = 'layout-builder';
+    }
+
+    if ($rel === 'layout-builder') {
+      $rel = $this->getTargetEntityTypeId() . '.' . $rel;
+    }
+    return parent::toUrl($rel, $options);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageInterface $storage, $update = TRUE) {
+    parent::preSave($storage, $update);
+
+    // Ensure the plugin configuration is updated. Once layouts are no longer
+    // stored as third party settings, this will be handled by the code in
+    // \Drupal\Core\Config\Entity\ConfigEntityBase::preSave() that handles
+    // \Drupal\Core\Entity\EntityWithPluginCollectionInterface.
+    foreach ($this->getSections() as $delta => $section) {
+      $this->setSection($delta, $section);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDefaultRegion($delta = 0) {
+    $sections = $this->getSections();
+    if (!isset($sections[$delta])) {
+      return parent::getDefaultRegion();
+    }
+
+    $section = $this->getSection($delta);
+    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');
+  }
+
+  /**
+   * {@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('view')) {
+            unset($build_list[$id][$name]);
+          }
+        }
+
+        foreach ($sections as $delta => $section) {
+          $build_list[$id]['_layout_builder'][$delta] = $section->toRenderArray();
+        }
+      }
+    }
+
+    return $build_list;
+  }
+
+  /**
+   * 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 getStorageType() {
+    return 'defaults';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getStorageId() {
+    return $this->id();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCanonicalUrl() {
+    // Defaults do not have a canonical URL, go to the Layout Builder UI.
+    return $this->getLayoutBuilderUrl();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLayoutBuilderUrl() {
+    return $this->toUrl('layout-builder');
+  }
+
+}
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..fc4f766a87
--- /dev/null
+++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplayStorage.php
@@ -0,0 +1,100 @@
+<?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.
+ */
+class LayoutBuilderEntityViewDisplayStorage extends ConfigEntityStorage {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function mapToStorageRecord(EntityInterface $entity) {
+    $record = parent::mapToStorageRecord($entity);
+
+    if (!empty($record['third_party_settings']['layout_builder']['sections'])) {
+      /** @var \Drupal\layout_builder\Section[] $sections */
+      $sections = &$record['third_party_settings']['layout_builder']['sections'];
+      foreach ($sections as $section_delta => $section) {
+        $sections[$section_delta] = [
+          'layout_id' => $section->getLayoutId(),
+          'layout_settings' => $section->getLayoutSettings(),
+          'components' => $this->exportComponents($section->getComponents()),
+        ];
+      }
+    }
+    return $record;
+  }
+
+  /**
+   * Exports an array of component objects into an array suitable for storage.
+   *
+   * @param \Drupal\layout_builder\SectionComponent[] $components
+   *   The component objects.
+   *
+   * @return mixed[]
+   *   An array of components in array form.
+   */
+  protected function exportComponents(array $components) {
+    $export = [];
+    foreach ($components as $delta => $component) {
+      $configuration_reflection = new \ReflectionProperty($component, 'configuration');
+      $configuration_reflection->setAccessible(TRUE);
+
+      $additional_reflection = new \ReflectionProperty($component, 'additional');
+      $additional_reflection->setAccessible(TRUE);
+
+      $export[$delta] = [
+        'uuid' => $component->getUuid(),
+        'region' => $component->getRegion(),
+        'configuration' => $configuration_reflection->getValue($component),
+        'additional' => $additional_reflection->getValue($component),
+        'weight' => $component->getWeight(),
+      ];
+    }
+    return $export;
+  }
+
+  /**
+   * {@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'],
+            $this->importComponents($section['components'])
+          );
+        }
+      }
+    }
+    return parent::mapFromStorageRecords($records);
+  }
+
+  /**
+   * Converts the array of component data back into objects.
+   *
+   * @param mixed[] $components
+   *   An array of component data.
+   *
+   * @return \Drupal\layout_builder\SectionComponent[]
+   *   An array of component objects.
+   */
+  protected function importComponents(array $components) {
+    $import = [];
+    foreach ($components as $delta => $component) {
+      $import[$delta] = (new SectionComponent($component['uuid'], $component['region'], $component['configuration'], $component['additional']))->setWeight($component['weight']);
+    }
+    return $import;
+  }
+
+}
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..297055401e
--- /dev/null
+++ b/core/modules/layout_builder/src/Entity/LayoutEntityDisplayInterface.php
@@ -0,0 +1,33 @@
+<?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
+ */
+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 71b22b78bc..6cc2dad109 100644
--- a/core/modules/layout_builder/src/Field/LayoutSectionItemList.php
+++ b/core/modules/layout_builder/src/Field/LayoutSectionItemList.php
@@ -3,6 +3,7 @@
 namespace Drupal\layout_builder\Field;
 
 use Drupal\Core\Field\FieldItemList;
+use Drupal\layout_builder\OverridesSectionStorageInterface;
 use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionStorageInterface;
 
@@ -13,7 +14,7 @@
  *
  * @see \Drupal\layout_builder\Plugin\Field\FieldType\LayoutSectionItem
  */
-class LayoutSectionItemList extends FieldItemList implements SectionStorageInterface {
+class LayoutSectionItemList extends FieldItemList implements SectionStorageInterface, OverridesSectionStorageInterface {
 
   /**
    * {@inheritdoc}
@@ -117,6 +118,13 @@ public function getLayoutBuilderUrl() {
     return $this->getEntity()->toUrl('layout-builder');
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefaultSectionStorage() {
+    return EntityViewDisplay::collectRenderDisplay($this->getEntity(), 'default');
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/layout_builder/src/OverridesSectionStorageInterface.php b/core/modules/layout_builder/src/OverridesSectionStorageInterface.php
new file mode 100644
index 0000000000..e9e18d2946
--- /dev/null
+++ b/core/modules/layout_builder/src/OverridesSectionStorageInterface.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Drupal\layout_builder;
+
+/**
+ * Defines an interface for an object that stores layout sections for overrides.
+ */
+interface OverridesSectionStorageInterface {
+
+  /**
+   * Returns the corresponding defaults section storage for this override.
+   *
+   * @return \Drupal\layout_builder\SectionStorageInterface
+   *   The defaults section storage.
+   */
+  public function getDefaultSectionStorage();
+
+}
diff --git a/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php b/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php
index 0aacc0d052..1abc785838 100644
--- a/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php
+++ b/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php
@@ -48,7 +48,7 @@ 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) {
       $this->derivatives["entity.$entity_type_id.layout_builder"] = $base_plugin_definition + [
         'route_name' => "entity.$entity_type_id.layout_builder",
         'weight' => 15,
@@ -72,6 +72,28 @@ public function getDerivativeDefinitions($base_plugin_definition) {
         'weight' => 5,
         'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id],
       ];
+      if ($route_name = $entity_type->get('field_ui_base_route')) {
+        $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",
+          'weight' => 4,
+          'title' => $this->t('Manage layout'),
+          'base_route' => $route_name,
+          '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 0c59762056..f05b594bc4 100644
--- a/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php
+++ b/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php
@@ -5,6 +5,9 @@
 use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Routing\RouteBuildEvent;
+use Drupal\Core\Routing\RoutingEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\Routing\Route;
 
 /**
@@ -12,7 +15,7 @@
  *
  * @internal
  */
-class LayoutBuilderRoutes {
+class LayoutBuilderRoutes implements EventSubscriberInterface {
 
   /**
    * The entity type manager.
@@ -72,6 +75,55 @@ public function getRoutes() {
     return $routes;
   }
 
+  /**
+   * Alters existing routes for a specific collection.
+   *
+   * @param \Drupal\Core\Routing\RouteBuildEvent $event
+   *   The route build event.
+   */
+  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';
+
+        $defaults = [];
+        $defaults['entity_type_id'] = $entity_type_id;
+        $defaults['view_mode_name'] = 'default';
+
+        $defaults['section_storage_type'] = 'defaults';
+        // Provide an empty value to allow the section storage to be upcast.
+        $defaults['section_storage'] = '';
+
+        // 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();
+          }
+        }
+
+        $requirements = [];
+        $requirements['_field_ui_view_mode_access'] = 'administer ' . $entity_type_id . ' display';
+
+        $options = $entity_route->getOptions();
+        $options['parameters']['section_storage']['layout_builder_tempstore'] = TRUE;
+
+        $routes = $this->buildRoute('entity.entity_view_display.' . $entity_type_id, $path, $defaults, $requirements, $options);
+        foreach ($routes as $name => $route) {
+          $collection->add($name, $route);
+        }
+      }
+    }
+  }
+
   /**
    * Builds the layout routes for the given values.
    *
@@ -150,4 +202,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/SectionStorageDefaultsParamConverter.php b/core/modules/layout_builder/src/Routing/SectionStorageDefaultsParamConverter.php
new file mode 100644
index 0000000000..e3f3550e7e
--- /dev/null
+++ b/core/modules/layout_builder/src/Routing/SectionStorageDefaultsParamConverter.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Drupal\layout_builder\Routing;
+
+use Drupal\Core\ParamConverter\EntityConverter;
+
+/**
+ * Provides a param converter for defaults-based section storage.
+ */
+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']) && !empty($defaults[$defaults['bundle_key']])) {
+        $defaults['bundle'] = $defaults[$defaults['bundle_key']];
+      }
+
+      $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 55204ddc9e..f4c65c5e19 100644
--- a/core/modules/layout_builder/src/Section.php
+++ b/core/modules/layout_builder/src/Section.php
@@ -70,14 +70,20 @@ public function __construct($layout_id, array $layout_settings = [], array $comp
    *   A renderable array representing the content of the section.
    */
   public function toRenderArray() {
-    $regions = [];
+    $layout = $this->getLayout();
+
+    // @todo Add the regions to the $build in the correct order. This is done
+    //   for parity with \Drupal\field_layout\FieldLayoutBuilder::buildView(),
+    //   which incorrectly adds all regions to the build.
+    $regions = array_fill_keys($layout->getPluginDefinition()->getRegionNames(), []);
+
     foreach ($this->getComponents() as $component) {
       if ($output = $component->toRenderArray()) {
         $regions[$component->getRegion()][$component->getUuid()] = $output;
       }
     }
 
-    return $this->getLayout()->build($regions);
+    return $layout->build($regions);
   }
 
   /**
diff --git a/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php b/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php
index 3f0bf9477e..d2842d7fea 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;
@@ -41,8 +41,8 @@ protected function setUp() {
     ]);
 
     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 = LayoutBuilderEntityViewDisplay::load('node.bundle_with_section_field.default');
+    $display->setOverridable();
     $display->save();
 
     $this->drupalLogin($this->drupalCreateUser([
diff --git a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
index 22bdaf51bd..c3c2fde042 100644
--- a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
+++ b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
@@ -92,7 +92,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();
+  }
+
+}
