diff --git a/config/schema/page_manager.schema.yml b/config/schema/page_manager.schema.yml
index 49e5cfc..95b1483 100644
--- a/config/schema/page_manager.schema.yml
+++ b/config/schema/page_manager.schema.yml
@@ -142,3 +142,12 @@ display_variant.plugin.http_status_code:
     redirect_location:
       type: string
       label: 'Redirect location'
+
+display_variant.plugin.layout_builder:
+  type: display_variant.plugin
+  label: 'Layout Builder'
+  mapping:
+    sections:
+      type: sequence
+      sequence:
+        type: layout_builder.section
diff --git a/page_manager.module b/page_manager.module
new file mode 100644
index 0000000..7acfd65
--- /dev/null
+++ b/page_manager.module
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Provides a way to place blocks on a custom page.
+ */
+
+use Drupal\page_manager\Entity\LayoutBuilderStorage;
+use Drupal\page_manager\Form\LayoutBuilderForm;
+
+/**
+ * Implements hook_entity_type_build().
+ */
+function page_manager_entity_type_build(array &$entity_types) {
+  if (_page_manager_is_layout_builder_enabled()) {
+    /* @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
+    $entity_types['page_variant']
+      ->setHandlerClass('storage', LayoutBuilderStorage::class)
+      ->setFormClass('layout_builder', LayoutBuilderForm::class);
+  }
+}
+
+/**
+ * Implements hook_display_variant_plugin_alter().
+ */
+function page_manager_display_variant_plugin_alter(array &$definitions) {
+  // Disable the layout builder plugin if layout builder is not enabled.
+  if (!_page_manager_is_layout_builder_enabled()) {
+    unset($definitions['layout_builder']);
+  }
+}
+
+/**
+ * Helper to check if layout builder is enabled.
+ *
+ * @return bool
+ *   TRUE is layout_builder is enabled, otherwise FALSE.
+ */
+function _page_manager_is_layout_builder_enabled() {
+  return Drupal::moduleHandler()->moduleExists('layout_builder');
+}
diff --git a/page_manager_ui/page_manager_ui.module b/page_manager_ui/page_manager_ui.module
index 6812a24..5ffbb32 100644
--- a/page_manager_ui/page_manager_ui.module
+++ b/page_manager_ui/page_manager_ui.module
@@ -139,3 +139,40 @@ function page_manager_ui_local_tasks_alter(&$local_tasks) {
   unset($local_tasks['config_translation.local_tasks:entity.page.config_translation_overview']);
   unset($local_tasks['config_translation.local_tasks:entity.page_variant.config_translation_overview']);
 }
+
+/**
+ * Implements hook_theme_registry_alter().
+ *
+ * @todo Refactor/remove if https://www.drupal.org/project/drupal/issues/3005403 lands.
+ */
+function page_manager_ui_theme_registry_alter(&$theme_registry) {
+  // Seven removes all block contextual links via a preprocess.
+  // Layout builder variants require contextual links to configure blocks.
+  // @see https://www.drupal.org/project/drupal/issues/2487025
+  if (!empty($theme_registry['block']['preprocess functions'])) {
+    $preprocess_functions = &$theme_registry['block']['preprocess functions'];
+
+    // Remove seven's implementation.
+    if ($index = array_search('seven_preprocess_block', $preprocess_functions)) {
+      unset($preprocess_functions[$index]);
+    }
+  }
+}
+
+/**
+ * Implements hook_preprocess_HOOK().
+ *
+ * @todo Refactor/remove if https://www.drupal.org/project/drupal/issues/3005403 lands.
+ */
+function page_manager_ui_preprocess_block(&$variables) {
+  if (Drupal::theme()->getActiveTheme()->getName() === 'seven') {
+    // If active theme is seven and the block has layout_builder contextual
+    // links, do nothing.
+    if (isset($variables['elements']['#contextual_links']['layout_builder_block'])) {
+      return;
+    }
+
+    // Fallback to seven.
+    seven_preprocess_block($variables);
+  }
+}
diff --git a/page_manager_ui/src/Form/PageVariantConfigureForm.php b/page_manager_ui/src/Form/PageVariantConfigureForm.php
index 8008081..2cde00f 100644
--- a/page_manager_ui/src/Form/PageVariantConfigureForm.php
+++ b/page_manager_ui/src/Form/PageVariantConfigureForm.php
@@ -38,7 +38,7 @@ class PageVariantConfigureForm extends FormBase {
     ];
 
     $variant_plugin = $page_variant->getVariantPlugin();
-    $form['variant_settings'] = $variant_plugin->buildConfigurationForm([], (new FormState())->setValues($form_state->getValue('variant_settings', [])));
+    $form['variant_settings'] = $variant_plugin->buildConfigurationForm([], (new FormState())->setValues($form_state->getValue('variant_settings', []) + ['page_variant' => $page_variant]));
     $form['variant_settings']['#tree'] = TRUE;
 
     if (!$page->isNew()) {
diff --git a/patch.patch b/patch.patch
new file mode 100644
index 0000000..8b0176e
--- /dev/null
+++ b/patch.patch
@@ -0,0 +1,904 @@
+diff --git a/config/schema/page_manager.schema.yml b/config/schema/page_manager.schema.yml
+index 49e5cfc..95b1483 100644
+--- a/config/schema/page_manager.schema.yml
++++ b/config/schema/page_manager.schema.yml
+@@ -142,3 +142,12 @@ display_variant.plugin.http_status_code:
+     redirect_location:
+       type: string
+       label: 'Redirect location'
++
++display_variant.plugin.layout_builder:
++  type: display_variant.plugin
++  label: 'Layout Builder'
++  mapping:
++    sections:
++      type: sequence
++      sequence:
++        type: layout_builder.section
+diff --git a/page_manager.module b/page_manager.module
+new file mode 100644
+index 0000000..7acfd65
+--- /dev/null
++++ b/page_manager.module
+@@ -0,0 +1,41 @@
++<?php
++
++/**
++ * @file
++ * Provides a way to place blocks on a custom page.
++ */
++
++use Drupal\page_manager\Entity\LayoutBuilderStorage;
++use Drupal\page_manager\Form\LayoutBuilderForm;
++
++/**
++ * Implements hook_entity_type_build().
++ */
++function page_manager_entity_type_build(array &$entity_types) {
++  if (_page_manager_is_layout_builder_enabled()) {
++    /* @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
++    $entity_types['page_variant']
++      ->setHandlerClass('storage', LayoutBuilderStorage::class)
++      ->setFormClass('layout_builder', LayoutBuilderForm::class);
++  }
++}
++
++/**
++ * Implements hook_display_variant_plugin_alter().
++ */
++function page_manager_display_variant_plugin_alter(array &$definitions) {
++  // Disable the layout builder plugin if layout builder is not enabled.
++  if (!_page_manager_is_layout_builder_enabled()) {
++    unset($definitions['layout_builder']);
++  }
++}
++
++/**
++ * Helper to check if layout builder is enabled.
++ *
++ * @return bool
++ *   TRUE is layout_builder is enabled, otherwise FALSE.
++ */
++function _page_manager_is_layout_builder_enabled() {
++  return Drupal::moduleHandler()->moduleExists('layout_builder');
++}
+diff --git a/page_manager_ui/page_manager_ui.module b/page_manager_ui/page_manager_ui.module
+index 6812a24..5ffbb32 100644
+--- a/page_manager_ui/page_manager_ui.module
++++ b/page_manager_ui/page_manager_ui.module
+@@ -139,3 +139,40 @@ function page_manager_ui_local_tasks_alter(&$local_tasks) {
+   unset($local_tasks['config_translation.local_tasks:entity.page.config_translation_overview']);
+   unset($local_tasks['config_translation.local_tasks:entity.page_variant.config_translation_overview']);
+ }
++
++/**
++ * Implements hook_theme_registry_alter().
++ *
++ * @todo Refactor/remove if https://www.drupal.org/project/drupal/issues/3005403 lands.
++ */
++function page_manager_ui_theme_registry_alter(&$theme_registry) {
++  // Seven removes all block contextual links via a preprocess.
++  // Layout builder variants require contextual links to configure blocks.
++  // @see https://www.drupal.org/project/drupal/issues/2487025
++  if (!empty($theme_registry['block']['preprocess functions'])) {
++    $preprocess_functions = &$theme_registry['block']['preprocess functions'];
++
++    // Remove seven's implementation.
++    if ($index = array_search('seven_preprocess_block', $preprocess_functions)) {
++      unset($preprocess_functions[$index]);
++    }
++  }
++}
++
++/**
++ * Implements hook_preprocess_HOOK().
++ *
++ * @todo Refactor/remove if https://www.drupal.org/project/drupal/issues/3005403 lands.
++ */
++function page_manager_ui_preprocess_block(&$variables) {
++  if (Drupal::theme()->getActiveTheme()->getName() === 'seven') {
++    // If active theme is seven and the block has layout_builder contextual
++    // links, do nothing.
++    if (isset($variables['elements']['#contextual_links']['layout_builder_block'])) {
++      return;
++    }
++
++    // Fallback to seven.
++    seven_preprocess_block($variables);
++  }
++}
+diff --git a/page_manager_ui/src/Form/PageVariantConfigureForm.php b/page_manager_ui/src/Form/PageVariantConfigureForm.php
+index 8008081..2cde00f 100644
+--- a/page_manager_ui/src/Form/PageVariantConfigureForm.php
++++ b/page_manager_ui/src/Form/PageVariantConfigureForm.php
+@@ -38,7 +38,7 @@ class PageVariantConfigureForm extends FormBase {
+     ];
+ 
+     $variant_plugin = $page_variant->getVariantPlugin();
+-    $form['variant_settings'] = $variant_plugin->buildConfigurationForm([], (new FormState())->setValues($form_state->getValue('variant_settings', [])));
++    $form['variant_settings'] = $variant_plugin->buildConfigurationForm([], (new FormState())->setValues($form_state->getValue('variant_settings', []) + ['page_variant' => $page_variant]));
+     $form['variant_settings']['#tree'] = TRUE;
+ 
+     if (!$page->isNew()) {
+diff --git a/src/Entity/LayoutBuilderStorage.php b/src/Entity/LayoutBuilderStorage.php
+new file mode 100644
+index 0000000..aa73f67
+--- /dev/null
++++ b/src/Entity/LayoutBuilderStorage.php
+@@ -0,0 +1,41 @@
++<?php
++
++namespace Drupal\page_manager\Entity;
++
++use Drupal\Core\Config\Entity\ConfigEntityStorage;
++use Drupal\Core\Entity\EntityInterface;
++use Drupal\layout_builder\Section;
++
++/**
++ * Provides storage for page manager entities that have layouts.
++ */
++class LayoutBuilderStorage extends ConfigEntityStorage {
++
++  /**
++   * {@inheritdoc}
++   */
++  protected function mapToStorageRecord(EntityInterface $entity) {
++    $record = parent::mapToStorageRecord($entity);
++
++    if (!empty($record['variant_settings']['sections'])) {
++      $record['variant_settings']['sections'] = array_map(function (Section $section) {
++        return $section->toArray();
++      }, $record['variant_settings']['sections']);
++    }
++    return $record;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  protected function mapFromStorageRecords(array $records) {
++    foreach ($records as &$record) {
++      if (!empty($record['variant_settings']['sections'])) {
++        $sections = &$record['variant_settings']['sections'];
++        $sections = array_map([Section::class, 'fromArray'], $sections);
++      }
++    }
++    return parent::mapFromStorageRecords($records);
++  }
++
++}
+diff --git a/src/Form/LayoutBuilderForm.php b/src/Form/LayoutBuilderForm.php
+new file mode 100644
+index 0000000..9c80ec4
+--- /dev/null
++++ b/src/Form/LayoutBuilderForm.php
+@@ -0,0 +1,140 @@
++<?php
++
++namespace Drupal\page_manager\Form;
++
++use Drupal\Core\Form\FormBase;
++use Drupal\Core\Form\FormStateInterface;
++use Drupal\Core\Plugin\Context\EntityContext;
++use Drupal\Core\TempStore\SharedTempStoreFactory;
++use Drupal\layout_builder\Form\PreviewToggleTrait;
++use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
++use Drupal\layout_builder\SectionStorage\SectionStorageManager;
++use Symfony\Component\DependencyInjection\ContainerInterface;
++
++/**
++ * Provides a form containing the Layout Builder UI for Page Manager.
++ *
++ * @todo Refactor this after https://www.drupal.org/node/3035189 is resolved.
++ */
++class LayoutBuilderForm extends FormBase {
++
++  use PreviewToggleTrait;
++
++  /**
++   * Layout tempstore repository.
++   *
++   * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
++   */
++  protected $layoutTempstoreRepository;
++
++  /**
++   * The Section Storage Manager.
++   *
++   * @var \Drupal\layout_builder\SectionStorage\SectionStorageManager
++   */
++  protected $sectionStorageManager;
++
++  /**
++   * The section storage.
++   *
++   * @var \Drupal\layout_builder\SectionStorageInterface
++   */
++  protected $sectionStorage;
++
++  /**
++   * The tempstore directory.
++   *
++   * @var \Drupal\Core\TempStore\SharedTempStoreFactory
++   */
++  protected $tempstore;
++
++  /**
++   * Constructs a new LayoutBuilderForm.
++   *
++   * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
++   *   The layout tempstore repository.
++   * @param \Drupal\layout_builder\SectionStorage\SectionStorageManager $section_storage_manager
++   *   The section storage manager.
++   * @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
++   *   The tempstore factory.
++   */
++  public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, SectionStorageManager $section_storage_manager, SharedTempStoreFactory $tempstore) {
++    $this->layoutTempstoreRepository = $layout_tempstore_repository;
++    $this->sectionStorageManager = $section_storage_manager;
++    $this->tempstore = $tempstore;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public static function create(ContainerInterface $container) {
++    return new static(
++      $container->get('layout_builder.tempstore_repository'),
++      $container->get('plugin.manager.layout_builder.section_storage'),
++      $container->get('tempstore.shared')
++    );
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getFormId() {
++    return 'page_manager_layout_builder_form';
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function buildForm(array $form, FormStateInterface $form_state) {
++    $cached_values = $form_state->getTemporaryValue('wizard');
++    /** @var \Drupal\page_manager\PageVariantInterface $page_variant */
++    $page_variant = $cached_values['page_variant'];
++
++    // If this is a new variant, put it in the tempstore so that we can
++    // retrieve it by id later.
++    // @see \Drupal\page_manager\Plugin\SectionStorage\PageManagerSectionStorage::deriveContextsFromRoute.
++    if ($page_variant->isNew()) {
++      $this->tempstore->get('page_manager.layout_builder')->set($page_variant->id(), $page_variant);
++    }
++
++    $section_storage = $this->sectionStorageManager->load('page_manager', [
++      'entity' => EntityContext::fromEntity($page_variant),
++    ]);
++
++    $this->sectionStorage = $this->layoutTempstoreRepository->get($section_storage);
++
++    $form['preview_toggle'] = $this->buildContentPreviewToggle();
++
++    $form['layout_builder'] = [
++      '#type' => 'layout_builder',
++      '#section_storage' => $this->sectionStorage,
++    ];
++
++    return $form;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function submitForm(array &$form, FormStateInterface $form_state) {
++    $cached_values = $form_state->getTemporaryValue('wizard');
++
++    /** @var \Drupal\page_manager\Entity\PageVariant $page_variant */
++    $page_variant = $this->sectionStorage->getContextValue('entity');
++
++    // Pass down the variant settings and let the plugin handle saving it.
++    /** @var \Drupal\page_manager\Plugin\DisplayVariant\LayoutBuilderDisplayVariant $variant_plugin */
++    $variant_plugin = $cached_values['plugin'];
++    $variant_plugin->setConfiguration($page_variant->get('variant_settings'));
++
++    // The form wizard takes care of saving the variant.
++    // Clear the layout tempstore.
++    $this->layoutTempstoreRepository->delete($this->sectionStorage);
++    $this->messenger()->addMessage($this->t('The layout has been saved.'));
++
++    // Clean up the tempstore.
++    $this->tempstore->get('page_manager.layout_builder')->delete($page_variant->id());
++    $this->tempstore->get('page_manager.page_variant')->delete($page_variant->id());
++  }
++
++}
+diff --git a/src/Plugin/DisplayVariant/LayoutBuilderDisplayVariant.php b/src/Plugin/DisplayVariant/LayoutBuilderDisplayVariant.php
+new file mode 100644
+index 0000000..925f2aa
+--- /dev/null
++++ b/src/Plugin/DisplayVariant/LayoutBuilderDisplayVariant.php
+@@ -0,0 +1,95 @@
++<?php
++
++namespace Drupal\page_manager\Plugin\DisplayVariant;
++
++use Drupal\Core\Display\VariantBase;
++use Drupal\Core\Form\FormStateInterface;
++use Drupal\ctools\Plugin\PluginWizardInterface;
++use Drupal\layout_builder\LayoutEntityHelperTrait;
++use Drupal\layout_builder\SectionStorage\SectionStorageTrait;
++use Drupal\page_manager\Form\LayoutBuilderForm;
++
++/**
++ * Provides a Layout Builder variant.
++ *
++ * @DisplayVariant(
++ *   id = "layout_builder",
++ *   admin_label = @Translation("Layout Builder")
++ * )
++ */
++class LayoutBuilderDisplayVariant extends VariantBase implements PluginWizardInterface {
++
++  use SectionStorageTrait;
++  use LayoutEntityHelperTrait;
++
++  /**
++   * {@inheritdoc}
++   */
++  public function build() {
++    $build = [];
++    foreach ($this->getSections() as $delta => $section) {
++      $build[$delta] = $section->toRenderArray();
++    }
++    return $build;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function defaultConfiguration() {
++    return parent::defaultConfiguration() + [
++      'sections' => [],
++    ];
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
++    return $form;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getWizardOperations($cached_values) {
++    $operations = [];
++    $operations['layout_builder'] = [
++      'title' => $this->t('Layout'),
++      'form' => LayoutBuilderForm::class,
++    ];
++
++    return $operations;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  protected function setSections(array $sections) {
++    $this->configuration['sections'] = array_values($sections);
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getSections() {
++    if (!isset($this->configuration['sections'])) {
++      $this->configuration['sections'] = [];
++    }
++    return $this->configuration['sections'];
++  }
++
++  /**
++   * Returns instance of the layout plugin used by this page variant.
++   *
++   * @return \Drupal\Core\Layout\LayoutInterface
++   *   A layout plugin instance.
++   */
++  public function getLayout() {
++    if (!isset($this->layout)) {
++      $this->layout = $this->layoutManager->createInstance($this->configuration['layout'], $this->configuration['layout_settings']);
++    }
++    return $this->layout;
++  }
++
++}
+diff --git a/src/Plugin/LayoutBuilderStorage/PageManagerLayoutBuilderStorage.php b/src/Plugin/LayoutBuilderStorage/PageManagerLayoutBuilderStorage.php
+new file mode 100644
+index 0000000..084ac32
+--- /dev/null
++++ b/src/Plugin/LayoutBuilderStorage/PageManagerLayoutBuilderStorage.php
+@@ -0,0 +1,122 @@
++<?php
++
++namespace Drupal\panels\Plugin\PanelsStorage;
++
++use Drupal\Core\Access\AccessResult;
++use Drupal\Core\Entity\EntityTypeManagerInterface;
++use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
++use Drupal\Core\Plugin\PluginBase;
++use Drupal\Core\Session\AccountInterface;
++use Drupal\page_manager\Plugin\DisplayVariant\LayoutBuilderDisplayVariant;
++use Symfony\Component\DependencyInjection\ContainerInterface;
++
++/**
++ * A Page Manager storage service that stores Layout Builder displays.
++ */
++class PageManagerLayoutBuilderStorage extends PluginBase implements ContainerFactoryPluginInterface {
++
++  /**
++   * The entity type manager.
++   *
++   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
++   */
++  protected $entityTypeManager;
++
++  /**
++   * Constructs a PageManagerLayoutBuilderStorage.
++   *
++   * @param array $configuration
++   *   A configuration array containing information about the plugin instance.
++   * @param string $plugin_id
++   *   The plugin_id for the plugin instance.
++   * @param mixed $plugin_definition
++   *   The plugin implementation definition.
++   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
++   *   The entity type manager.
++   */
++  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
++    parent::__construct($configuration, $plugin_id, $plugin_definition);
++    $this->entityTypeManager = $entity_type_manager;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
++    return new static(
++      $configuration,
++      $plugin_id,
++      $plugin_definition,
++      $container->get('entity_type.manager')
++    );
++  }
++
++  /**
++   * Load a page variant entity.
++   *
++   * @param string $id
++   *   The page variant entity's id.
++   *
++   * @return \Drupal\page_manager\PageVariantInterface
++   *   The variant object.
++   *
++   * @throws \Exception
++   */
++  protected function loadPageVariant($id) {
++    return $this->entityTypeManager->getStorage('page_variant')->load($id);
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function save(LayoutBuilderDisplayVariant $lb_display) {
++    $id = $lb_display->getStorageId();
++    if ($id && ($page_variant = $this->loadPageVariant($id))) {
++      $variant_plugin = $page_variant->getVariantPlugin();
++      if (!($variant_plugin instanceof LayoutBuilderDisplayVariant)) {
++        throw new \Exception("Page variant doesn't use a Layout Builder display variant");
++      }
++      $variant_plugin->setConfiguration($lb_display->getConfiguration());
++      $page_variant->save();
++    }
++    else {
++      throw new \Exception("Couldn't find page variant to store Layout Builder display");
++    }
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function load($id) {
++    if ($page_variant = $this->loadPageVariant($id)) {
++      $lb_display = $page_variant->getVariantPlugin();
++
++      // If this page variant doesn't have a Panels display on it, then we treat
++      // it the same as if there was no such page variant.
++      if (!($lb_display instanceof LayoutBuilderDisplayVariant)) {
++        return NULL;
++      }
++
++      // Pass down the contexts because the display has no other way to get them
++      // from the variant.
++      $lb_display->setContexts($page_variant->getContexts());
++
++      return $lb_display;
++    }
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function access($id, $op, AccountInterface $account) {
++    if ($op == 'change layout') {
++      $op = 'update';
++    }
++    if ($page_variant = $this->loadPageVariant($id)) {
++      return $page_variant->access($op, $account, TRUE);
++    }
++
++    return AccessResult::forbidden();
++  }
++
++}
+diff --git a/src/Plugin/SectionStorage/PageManagerSectionStorage.php b/src/Plugin/SectionStorage/PageManagerSectionStorage.php
+new file mode 100644
+index 0000000..97b42df
+--- /dev/null
++++ b/src/Plugin/SectionStorage/PageManagerSectionStorage.php
+@@ -0,0 +1,233 @@
++<?php
++
++namespace Drupal\page_manager\Plugin\SectionStorage;
++
++use Drupal\Core\Access\AccessResult;
++use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
++use Drupal\Core\Entity\EntityTypeManagerInterface;
++use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
++use Drupal\Core\Plugin\Context\EntityContext;
++use Drupal\Core\Session\AccountInterface;
++use Drupal\Core\TempStore\SharedTempStoreFactory;
++use Drupal\Core\Url;
++use Drupal\layout_builder\Entity\SampleEntityGeneratorInterface;
++use Drupal\layout_builder\Plugin\SectionStorage\SectionStorageBase;
++use Drupal\page_manager\Entity\PageVariant;
++use Drupal\page_manager\Plugin\DisplayVariant\LayoutBuilderDisplayVariant;
++use Symfony\Component\DependencyInjection\ContainerInterface;
++use Symfony\Component\Routing\RouteCollection;
++
++/**
++ * Defines the 'page_manager' section storage type.
++ *
++ * @SectionStorage(
++ *   id = "page_manager",
++ *   context_definitions = {
++ *     "entity" = @ContextDefinition("entity:page_variant"),
++ *   },
++ * )
++ */
++class PageManagerSectionStorage extends SectionStorageBase implements ContainerFactoryPluginInterface {
++
++  /**
++   * The entity type manager.
++   *
++   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
++   */
++  protected $entityTypeManager;
++
++  /**
++   * The sample entity generator.
++   *
++   * @var \Drupal\layout_builder\Entity\SampleEntityGeneratorInterface
++   */
++  protected $sampleEntityGenerator;
++
++  /**
++   * The tempstore factory.
++   *
++   * @var \Drupal\Core\TempStore\SharedTempStoreFactory
++   */
++  protected $tempstore;
++
++  /**
++   * PageManagerSectionStorage constructor.
++   *
++   * @param array $configuration
++   *   The plugin configuration, i.e. an array with configuration values keyed
++   *   by configuration option name. The special key 'context' may be used to
++   *   initialize the defined contexts by setting it to an array of context
++   *   values keyed by context names.
++   * @param string $plugin_id
++   *   The plugin_id for the plugin instance.
++   * @param mixed $plugin_definition
++   *   The plugin implementation definition.
++   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
++   *   The entity type manager.
++   * @param \Drupal\layout_builder\Entity\SampleEntityGeneratorInterface $sample_entity_generator
++   *   The sample entity generator.
++   * @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
++   *   The tempstore factory.
++   */
++  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, SampleEntityGeneratorInterface $sample_entity_generator, SharedTempStoreFactory $tempstore) {
++    parent::__construct($configuration, $plugin_id, $plugin_definition);
++
++    $this->entityTypeManager = $entity_type_manager;
++    $this->sampleEntityGenerator = $sample_entity_generator;
++    $this->tempstore = $tempstore;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
++    return new static(
++      $configuration,
++      $plugin_id,
++      $plugin_definition,
++      $container->get('entity_type.manager'),
++      $container->get('layout_builder.sample_entity_generator'),
++      $container->get('tempstore.shared')
++    );
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  protected function getSectionList() {
++    return $this->getContextValue('entity')->getVariantPlugin();
++  }
++
++  /**
++   * Gets the page variant entity.
++   *
++   * @return \Drupal\page_manager\Entity\PageVariant
++   *   The page variant entity.
++   *
++   * @throws \Drupal\Component\Plugin\Exception\PluginException
++   */
++  protected function getPageVariant() {
++    return $this->getContextValue('entity');
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getStorageId() {
++    return $this->getContextValue('entity')->id();
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getRedirectUrl() {
++    return Url::fromUri($this->getPageVariant()->getPage()->getPath());
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getLayoutBuilderUrl($rel = 'view') {
++    return Url::fromRoute("layout_builder.page_manager.view", ['page_variant' => $this->getPageVariant()->id()]);
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function buildRoutes(RouteCollection $collection) {
++    $path = '/admin/structure/page_manager/{page_variant}/layout';
++
++    $options['parameters']['page_variant']['type'] = 'entity:page_variant';
++
++    $options['_admin_route'] = FALSE;
++
++    $this->buildLayoutRoutes($collection, $this->getPluginDefinition(), $path, [], [], $options, '', 'page_variant');
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function deriveContextsFromRoute($value, $definition, $name, array $defaults) {
++    // Try to load from defaults.
++    $entity = $this->extractEntityFromRoute($value, $defaults);
++
++    // Otherwise try the tempstore.
++    if (!$entity) {
++      $entity = $this->tempstore->get('page_manager.layout_builder')->get($value);
++    }
++
++    return [
++      'entity' => EntityContext::fromEntity($entity),
++    ];
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  private function extractEntityFromRoute($value, array $defaults) {
++    if (!empty($value)) {
++      return PageVariant::load($value);
++    }
++
++    return PageVariant::load($defaults['page_variant']);
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function label() {
++    return $this->getPageVariant()->label();
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function save() {
++    $page_variant = $this->getPageVariant();
++    return $page_variant->save();
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
++    $result = AccessResult::allowedIf($this->isLayoutBuilderEnabled())->addCacheableDependency($this);
++    return $return_as_object ? $result : $result->isAllowed();
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function isApplicable(RefinableCacheableDependencyInterface $cacheability) {
++    return $this->isLayoutBuilderEnabled();
++  }
++
++  /**
++   * Determines if Layout Builder is enabled.
++   *
++   * @return bool
++   *   TRUE if Layout Builder is enabled, FALSE otherwise.
++   *
++   * @throws \Drupal\Component\Plugin\Exception\PluginException
++   */
++  public function isLayoutBuilderEnabled() {
++    return $this->getContextValue('entity')->getVariantPlugin() instanceof LayoutBuilderDisplayVariant;
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function getSectionListFromId($id) {
++    // @todo
++    // This is deprecated and can be removed before Drupal 9.0.0.
++  }
++
++  /**
++   * {@inheritdoc}
++   */
++  public function extractIdFromRoute($value, $definition, $name, array $defaults) {
++    // @todo
++    // This is deprecated and can be removed before Drupal 9.0.0.
++  }
++
++}
+diff --git a/tests/src/FunctionalJavascript/LayoutBuilderDisplayVariantTest.php b/tests/src/FunctionalJavascript/LayoutBuilderDisplayVariantTest.php
+new file mode 100644
+index 0000000..e464a2c
+--- /dev/null
++++ b/tests/src/FunctionalJavascript/LayoutBuilderDisplayVariantTest.php
+@@ -0,0 +1,115 @@
++<?php
++
++namespace Drupal\Tests\page_manager\FunctionalJavascript;
++
++use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
++use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
++use Drupal\Tests\user\Traits\UserCreationTrait;
++
++/**
++ * Test the layout_builder variant plugin.
++ *
++ * @group page_manager
++ */
++class LayoutBuilderDisplayVariantTest extends WebDriverTestBase {
++
++  use UserCreationTrait;
++  use ContextualLinkClickTrait;
++
++  /**
++   * {@inheritdoc}
++   */
++  protected static $modules = [
++    'layout_builder',
++    'page_manager_ui',
++  ];
++
++  /**
++   * {@inheritdoc}
++   */
++  protected function setUp() {
++    parent::setUp();
++
++    $this->drupalLogin($this->createUser(array_keys($this->container->get('user.permissions')
++      ->getPermissions())));
++  }
++
++  /**
++   * Tests the layout builder variant.
++   */
++  public function testLayoutBuilderVariant() {
++    $this->drupalGet('admin/structure/page_manager/add');
++    $page = $this->getSession()->getPage();
++    $assert_session = $this->assertSession();
++
++    $page->fillField('label', 'Example');
++    $assert_session->waitForElementVisible('css', '.machine-name-value');
++    $this->submitForm([
++      'path' => '/example',
++      'variant_plugin_id' => 'layout_builder',
++    ], t('Next'));
++
++    $this->submitForm([
++      'page_variant_label' => 'Layout Builder',
++    ], t('Next'));
++
++    // Add a two column section.
++    $page->find('css', '.layout-builder__link--add')->click();
++    $assert_session->waitForElementVisible('named', ['link', 'One column']);
++    $this->clickLink('Two column');
++    $assert_session->assertWaitOnAjaxRequest();
++    $page->pressButton('Add section');
++    $assert_session->assertWaitOnAjaxRequest();
++
++    // Place a block in the first region.
++    $page->find('css', '.layout__region--first .layout-builder__link--add')
++      ->click();
++    $assert_session->assertWaitOnAjaxRequest();
++    $this->clickLink('Powered by Drupal');
++    $assert_session->assertWaitOnAjaxRequest();
++    $page->find('css', 'form.layout-builder-add-block .form-submit')->click();
++    $assert_session->assertWaitOnAjaxRequest();
++    $assert_session->pageTextContains('Powered by Drupal');
++
++    // Test content preview.
++    $page->uncheckField('toggle_content_preview');
++    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.layout-builder-block__content-preview-placeholder-label'));
++
++    $page->pressButton('Finish');
++    $assert_session->pageTextContains('The layout has been saved.');
++
++    // Go the layout builder variant.
++    $this->drupalGet('admin/structure/page_manager/manage/example/page_variant__example-layout_builder-0__layout_builder');
++
++    // Place another block in the first region.
++    $page->find('css', '.layout__region--first .layout-builder__link--add')
++      ->click();
++    $assert_session->assertWaitOnAjaxRequest();
++    $this->clickLink('User account menu');
++    $assert_session->assertWaitOnAjaxRequest();
++    $page->find('css', 'form.layout-builder-add-block .form-submit')->click();
++    $assert_session->assertWaitOnAjaxRequest();
++    $assert_session->pageTextContains('User account menu');
++
++    // Test drag and drop.
++    $page->find('css', '.layout__region--first .menu--account')
++      ->dragTo($page->find('css', '.layout__region--second'));
++    $assert_session->assertWaitOnAjaxRequest();
++
++    // Test contextual links.
++    $assert_session->waitForElement('css', '.block-system-powered-by-block .contextual');
++    $this->clickContextualLink('.block-system-powered-by-block', 'Configure');
++    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas'));
++
++    // Save page.
++    $page->pressButton('Update and save');
++
++    // Check if block is rendered in the correct region.
++    $this->drupalGet('example');
++    $assert_session->waitForElementVisible('css', '.layout__region--first');
++    $assert_session->elementTextContains('css', '.layout__region--first', 'Powered by Drupal');
++    $assert_session->waitForElementVisible('css', '.layout__region--second');
++    $assert_session->elementTextContains('css', '.layout__region--second', 'User account menu');
++  }
++
++}
diff --git a/src/Entity/LayoutBuilderStorage.php b/src/Entity/LayoutBuilderStorage.php
new file mode 100644
index 0000000..aa73f67
--- /dev/null
+++ b/src/Entity/LayoutBuilderStorage.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Drupal\page_manager\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityStorage;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\layout_builder\Section;
+
+/**
+ * Provides storage for page manager entities that have layouts.
+ */
+class LayoutBuilderStorage extends ConfigEntityStorage {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function mapToStorageRecord(EntityInterface $entity) {
+    $record = parent::mapToStorageRecord($entity);
+
+    if (!empty($record['variant_settings']['sections'])) {
+      $record['variant_settings']['sections'] = array_map(function (Section $section) {
+        return $section->toArray();
+      }, $record['variant_settings']['sections']);
+    }
+    return $record;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function mapFromStorageRecords(array $records) {
+    foreach ($records as &$record) {
+      if (!empty($record['variant_settings']['sections'])) {
+        $sections = &$record['variant_settings']['sections'];
+        $sections = array_map([Section::class, 'fromArray'], $sections);
+      }
+    }
+    return parent::mapFromStorageRecords($records);
+  }
+
+}
diff --git a/src/Form/LayoutBuilderForm.php b/src/Form/LayoutBuilderForm.php
new file mode 100644
index 0000000..9c80ec4
--- /dev/null
+++ b/src/Form/LayoutBuilderForm.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace Drupal\page_manager\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\TempStore\SharedTempStoreFactory;
+use Drupal\layout_builder\Form\PreviewToggleTrait;
+use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
+use Drupal\layout_builder\SectionStorage\SectionStorageManager;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a form containing the Layout Builder UI for Page Manager.
+ *
+ * @todo Refactor this after https://www.drupal.org/node/3035189 is resolved.
+ */
+class LayoutBuilderForm extends FormBase {
+
+  use PreviewToggleTrait;
+
+  /**
+   * Layout tempstore repository.
+   *
+   * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
+   */
+  protected $layoutTempstoreRepository;
+
+  /**
+   * The Section Storage Manager.
+   *
+   * @var \Drupal\layout_builder\SectionStorage\SectionStorageManager
+   */
+  protected $sectionStorageManager;
+
+  /**
+   * The section storage.
+   *
+   * @var \Drupal\layout_builder\SectionStorageInterface
+   */
+  protected $sectionStorage;
+
+  /**
+   * The tempstore directory.
+   *
+   * @var \Drupal\Core\TempStore\SharedTempStoreFactory
+   */
+  protected $tempstore;
+
+  /**
+   * Constructs a new LayoutBuilderForm.
+   *
+   * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
+   *   The layout tempstore repository.
+   * @param \Drupal\layout_builder\SectionStorage\SectionStorageManager $section_storage_manager
+   *   The section storage manager.
+   * @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
+   *   The tempstore factory.
+   */
+  public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, SectionStorageManager $section_storage_manager, SharedTempStoreFactory $tempstore) {
+    $this->layoutTempstoreRepository = $layout_tempstore_repository;
+    $this->sectionStorageManager = $section_storage_manager;
+    $this->tempstore = $tempstore;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('layout_builder.tempstore_repository'),
+      $container->get('plugin.manager.layout_builder.section_storage'),
+      $container->get('tempstore.shared')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'page_manager_layout_builder_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $cached_values = $form_state->getTemporaryValue('wizard');
+    /** @var \Drupal\page_manager\PageVariantInterface $page_variant */
+    $page_variant = $cached_values['page_variant'];
+
+    // If this is a new variant, put it in the tempstore so that we can
+    // retrieve it by id later.
+    // @see \Drupal\page_manager\Plugin\SectionStorage\PageManagerSectionStorage::deriveContextsFromRoute.
+    if ($page_variant->isNew()) {
+      $this->tempstore->get('page_manager.layout_builder')->set($page_variant->id(), $page_variant);
+    }
+
+    $section_storage = $this->sectionStorageManager->load('page_manager', [
+      'entity' => EntityContext::fromEntity($page_variant),
+    ]);
+
+    $this->sectionStorage = $this->layoutTempstoreRepository->get($section_storage);
+
+    $form['preview_toggle'] = $this->buildContentPreviewToggle();
+
+    $form['layout_builder'] = [
+      '#type' => 'layout_builder',
+      '#section_storage' => $this->sectionStorage,
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $cached_values = $form_state->getTemporaryValue('wizard');
+
+    /** @var \Drupal\page_manager\Entity\PageVariant $page_variant */
+    $page_variant = $this->sectionStorage->getContextValue('entity');
+
+    // Pass down the variant settings and let the plugin handle saving it.
+    /** @var \Drupal\page_manager\Plugin\DisplayVariant\LayoutBuilderDisplayVariant $variant_plugin */
+    $variant_plugin = $cached_values['plugin'];
+    $variant_plugin->setConfiguration($page_variant->get('variant_settings'));
+
+    // The form wizard takes care of saving the variant.
+    // Clear the layout tempstore.
+    $this->layoutTempstoreRepository->delete($this->sectionStorage);
+    $this->messenger()->addMessage($this->t('The layout has been saved.'));
+
+    // Clean up the tempstore.
+    $this->tempstore->get('page_manager.layout_builder')->delete($page_variant->id());
+    $this->tempstore->get('page_manager.page_variant')->delete($page_variant->id());
+  }
+
+}
diff --git a/src/Plugin/DisplayVariant/LayoutBuilderDisplayVariant.php b/src/Plugin/DisplayVariant/LayoutBuilderDisplayVariant.php
new file mode 100644
index 0000000..3ab6467
--- /dev/null
+++ b/src/Plugin/DisplayVariant/LayoutBuilderDisplayVariant.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace Drupal\page_manager\Plugin\DisplayVariant;
+
+use Drupal\Core\Display\ContextAwareVariantInterface;
+use Drupal\Core\Display\VariantBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\ctools\Plugin\PluginWizardInterface;
+use Drupal\layout_builder\LayoutEntityHelperTrait;
+use Drupal\layout_builder\SectionStorage\SectionStorageTrait;
+use Drupal\page_manager\Form\LayoutBuilderForm;
+
+/**
+ * Provides a Layout Builder variant.
+ *
+ * @DisplayVariant(
+ *   id = "layout_builder",
+ *   admin_label = @Translation("Layout Builder")
+ * )
+ */
+class LayoutBuilderDisplayVariant extends VariantBase implements PluginWizardInterface, ContextAwareVariantInterface {
+
+  use SectionStorageTrait;
+  use LayoutEntityHelperTrait;
+
+  /**
+   * An array of collected contexts.
+   *
+   * This is only used on runtime, and is not stored.
+   *
+   * @var \Drupal\Component\Plugin\Context\ContextInterface[]
+   */
+  protected $contexts = [];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build() {
+    $build = [];
+    $contexts = $this->getContexts();
+    foreach ($this->getSections() as $delta => $section) {
+      $build[$delta] = $section->toRenderArray($contexts);
+    }
+    return $build;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return parent::defaultConfiguration() + [
+      'sections' => [],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getWizardOperations($cached_values) {
+    $operations = [];
+    $operations['layout_builder'] = [
+      'title' => $this->t('Layout'),
+      'form' => LayoutBuilderForm::class,
+    ];
+
+    return $operations;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setSections(array $sections) {
+    $this->configuration['sections'] = array_values($sections);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSections() {
+    if (!isset($this->configuration['sections'])) {
+      $this->configuration['sections'] = [];
+    }
+    return $this->configuration['sections'];
+  }
+
+  /**
+   * Returns instance of the layout plugin used by this page variant.
+   *
+   * @return \Drupal\Core\Layout\LayoutInterface
+   *   A layout plugin instance.
+   */
+  public function getLayout() {
+    if (!isset($this->layout)) {
+      $this->layout = $this->layoutManager->createInstance($this->configuration['layout'], $this->configuration['layout_settings']);
+    }
+    return $this->layout;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContexts() {
+    return $this->contexts;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContexts(array $contexts) {
+    $this->contexts = $contexts;
+    return $this;
+  }
+
+}
diff --git a/src/Plugin/LayoutBuilderStorage/PageManagerLayoutBuilderStorage.php b/src/Plugin/LayoutBuilderStorage/PageManagerLayoutBuilderStorage.php
new file mode 100644
index 0000000..084ac32
--- /dev/null
+++ b/src/Plugin/LayoutBuilderStorage/PageManagerLayoutBuilderStorage.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace Drupal\panels\Plugin\PanelsStorage;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Plugin\PluginBase;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\page_manager\Plugin\DisplayVariant\LayoutBuilderDisplayVariant;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * A Page Manager storage service that stores Layout Builder displays.
+ */
+class PageManagerLayoutBuilderStorage extends PluginBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a PageManagerLayoutBuilderStorage.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * Load a page variant entity.
+   *
+   * @param string $id
+   *   The page variant entity's id.
+   *
+   * @return \Drupal\page_manager\PageVariantInterface
+   *   The variant object.
+   *
+   * @throws \Exception
+   */
+  protected function loadPageVariant($id) {
+    return $this->entityTypeManager->getStorage('page_variant')->load($id);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save(LayoutBuilderDisplayVariant $lb_display) {
+    $id = $lb_display->getStorageId();
+    if ($id && ($page_variant = $this->loadPageVariant($id))) {
+      $variant_plugin = $page_variant->getVariantPlugin();
+      if (!($variant_plugin instanceof LayoutBuilderDisplayVariant)) {
+        throw new \Exception("Page variant doesn't use a Layout Builder display variant");
+      }
+      $variant_plugin->setConfiguration($lb_display->getConfiguration());
+      $page_variant->save();
+    }
+    else {
+      throw new \Exception("Couldn't find page variant to store Layout Builder display");
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load($id) {
+    if ($page_variant = $this->loadPageVariant($id)) {
+      $lb_display = $page_variant->getVariantPlugin();
+
+      // If this page variant doesn't have a Panels display on it, then we treat
+      // it the same as if there was no such page variant.
+      if (!($lb_display instanceof LayoutBuilderDisplayVariant)) {
+        return NULL;
+      }
+
+      // Pass down the contexts because the display has no other way to get them
+      // from the variant.
+      $lb_display->setContexts($page_variant->getContexts());
+
+      return $lb_display;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access($id, $op, AccountInterface $account) {
+    if ($op == 'change layout') {
+      $op = 'update';
+    }
+    if ($page_variant = $this->loadPageVariant($id)) {
+      return $page_variant->access($op, $account, TRUE);
+    }
+
+    return AccessResult::forbidden();
+  }
+
+}
diff --git a/src/Plugin/SectionStorage/PageManagerSectionStorage.php b/src/Plugin/SectionStorage/PageManagerSectionStorage.php
new file mode 100644
index 0000000..1c6b332
--- /dev/null
+++ b/src/Plugin/SectionStorage/PageManagerSectionStorage.php
@@ -0,0 +1,271 @@
+<?php
+
+namespace Drupal\page_manager\Plugin\SectionStorage;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\TempStore\SharedTempStoreFactory;
+use Drupal\Core\Url;
+use Drupal\layout_builder\Entity\SampleEntityGeneratorInterface;
+use Drupal\layout_builder\Plugin\SectionStorage\SectionStorageBase;
+use Drupal\page_manager\Entity\PageVariant;
+use Drupal\page_manager\Plugin\DisplayVariant\LayoutBuilderDisplayVariant;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * Defines the 'page_manager' section storage type.
+ *
+ * @SectionStorage(
+ *   id = "page_manager",
+ *   context_definitions = {
+ *     "entity" = @ContextDefinition("entity:page_variant"),
+ *   },
+ * )
+ */
+class PageManagerSectionStorage extends SectionStorageBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The sample entity generator.
+   *
+   * @var \Drupal\layout_builder\Entity\SampleEntityGeneratorInterface
+   */
+  protected $sampleEntityGenerator;
+
+  /**
+   * The tempstore factory.
+   *
+   * @var \Drupal\Core\TempStore\SharedTempStoreFactory
+   */
+  protected $tempstore;
+
+  /**
+   * The entity bundle info.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
+   */
+  protected $entityTypeBundleInfo;
+
+  /**
+   * PageManagerSectionStorage constructor.
+   *
+   * @param array $configuration
+   *   The plugin configuration, i.e. an array with configuration values keyed
+   *   by configuration option name. The special key 'context' may be used to
+   *   initialize the defined contexts by setting it to an array of context
+   *   values keyed by context names.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   * @param \Drupal\layout_builder\Entity\SampleEntityGeneratorInterface $sample_entity_generator
+   *   The sample entity generator.
+   * @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempstore
+   *   The tempstore factory.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, SampleEntityGeneratorInterface $sample_entity_generator, SharedTempStoreFactory $tempstore, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->entityTypeManager = $entity_type_manager;
+    $this->sampleEntityGenerator = $sample_entity_generator;
+    $this->tempstore = $tempstore;
+    $this->entityTypeBundleInfo = $entity_type_bundle_info;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_type.manager'),
+      $container->get('layout_builder.sample_entity_generator'),
+      $container->get('tempstore.shared'),
+      $container->get('entity_type.bundle.info')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getSectionList() {
+    return $this->getContextValue('entity')->getVariantPlugin();
+  }
+
+  /**
+   * Gets the page variant entity.
+   *
+   * @return \Drupal\page_manager\Entity\PageVariant
+   *   The page variant entity.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\PluginException
+   */
+  protected function getPageVariant() {
+    return $this->getContextValue('entity');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getStorageId() {
+    return $this->getContextValue('entity')->id();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRedirectUrl() {
+    return Url::fromUri($this->getPageVariant()->getPage()->getPath());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLayoutBuilderUrl($rel = 'view') {
+    return Url::fromRoute("layout_builder.page_manager.view", ['page_variant' => $this->getPageVariant()->id()]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildRoutes(RouteCollection $collection) {
+    $path = '/admin/structure/page_manager/{page_variant}/layout';
+
+    $options['parameters']['page_variant']['type'] = 'entity:page_variant';
+
+    $options['_admin_route'] = FALSE;
+
+    $this->buildLayoutRoutes($collection, $this->getPluginDefinition(), $path, [], [], $options, '', 'page_variant');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deriveContextsFromRoute($value, $definition, $name, array $defaults) {
+    // Try to load from defaults.
+    $entity = $this->extractEntityFromRoute($value, $defaults);
+
+    // Otherwise try the tempstore.
+    if (!$entity) {
+      $entity = $this->tempstore->get('page_manager.layout_builder')->get($value);
+    }
+
+    return [
+      'entity' => EntityContext::fromEntity($entity),
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  private function extractEntityFromRoute($value, array $defaults) {
+    if (!empty($value)) {
+      return PageVariant::load($value);
+    }
+
+    return PageVariant::load($defaults['page_variant']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function label() {
+    return $this->getPageVariant()->label();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save() {
+    $page_variant = $this->getPageVariant();
+    return $page_variant->save();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
+    $result = AccessResult::allowedIf($this->isLayoutBuilderEnabled())->addCacheableDependency($this);
+    return $return_as_object ? $result : $result->isAllowed();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isApplicable(RefinableCacheableDependencyInterface $cacheability) {
+    return $this->isLayoutBuilderEnabled();
+  }
+
+  /**
+   * Determines if Layout Builder is enabled.
+   *
+   * @return bool
+   *   TRUE if Layout Builder is enabled, FALSE otherwise.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\PluginException
+   */
+  public function isLayoutBuilderEnabled() {
+    return $this->getContextValue('entity')->getVariantPlugin() instanceof LayoutBuilderDisplayVariant;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSectionListFromId($id) {
+    // @todo
+    // This is deprecated and can be removed before Drupal 9.0.0.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function extractIdFromRoute($value, $definition, $name, array $defaults) {
+    // @todo
+    // This is deprecated and can be removed before Drupal 9.0.0.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContextsDuringPreview() {
+    $contexts = parent::getContextsDuringPreview();
+    $contexts += $this->getPageVariant()->getContexts() + $this->getPageVariant()->getStaticContexts();
+
+    foreach ($contexts as $name => $context) {
+      if (!$context->hasContextValue()) {
+        $data_type = $context->getContextDefinition()->getDataType();
+        if (strpos($data_type, 'entity:') === 0) {
+          list(, $entity_type_id) = explode(':', $data_type, 2);
+
+          $bundle = $entity_type_id;
+          if ($this->entityTypeManager->getDefinition($entity_type_id)->hasKey('bundle')) {
+            $bundle = key($this->entityTypeBundleInfo->getBundleInfo($entity_type_id));
+          }
+
+          $sample = $this->sampleEntityGenerator->get($entity_type_id, $bundle);
+          $contexts[$name] = Context::createFromContext($context, $sample);
+        }
+      }
+    }
+
+    return $contexts;
+  }
+
+}
diff --git a/tests/src/FunctionalJavascript/LayoutBuilderDisplayVariantTest.php b/tests/src/FunctionalJavascript/LayoutBuilderDisplayVariantTest.php
new file mode 100644
index 0000000..e464a2c
--- /dev/null
+++ b/tests/src/FunctionalJavascript/LayoutBuilderDisplayVariantTest.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace Drupal\Tests\page_manager\FunctionalJavascript;
+
+use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
+use Drupal\Tests\user\Traits\UserCreationTrait;
+
+/**
+ * Test the layout_builder variant plugin.
+ *
+ * @group page_manager
+ */
+class LayoutBuilderDisplayVariantTest extends WebDriverTestBase {
+
+  use UserCreationTrait;
+  use ContextualLinkClickTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'layout_builder',
+    'page_manager_ui',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->drupalLogin($this->createUser(array_keys($this->container->get('user.permissions')
+      ->getPermissions())));
+  }
+
+  /**
+   * Tests the layout builder variant.
+   */
+  public function testLayoutBuilderVariant() {
+    $this->drupalGet('admin/structure/page_manager/add');
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
+    $page->fillField('label', 'Example');
+    $assert_session->waitForElementVisible('css', '.machine-name-value');
+    $this->submitForm([
+      'path' => '/example',
+      'variant_plugin_id' => 'layout_builder',
+    ], t('Next'));
+
+    $this->submitForm([
+      'page_variant_label' => 'Layout Builder',
+    ], t('Next'));
+
+    // Add a two column section.
+    $page->find('css', '.layout-builder__link--add')->click();
+    $assert_session->waitForElementVisible('named', ['link', 'One column']);
+    $this->clickLink('Two column');
+    $assert_session->assertWaitOnAjaxRequest();
+    $page->pressButton('Add section');
+    $assert_session->assertWaitOnAjaxRequest();
+
+    // Place a block in the first region.
+    $page->find('css', '.layout__region--first .layout-builder__link--add')
+      ->click();
+    $assert_session->assertWaitOnAjaxRequest();
+    $this->clickLink('Powered by Drupal');
+    $assert_session->assertWaitOnAjaxRequest();
+    $page->find('css', 'form.layout-builder-add-block .form-submit')->click();
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->pageTextContains('Powered by Drupal');
+
+    // Test content preview.
+    $page->uncheckField('toggle_content_preview');
+    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.layout-builder-block__content-preview-placeholder-label'));
+
+    $page->pressButton('Finish');
+    $assert_session->pageTextContains('The layout has been saved.');
+
+    // Go the layout builder variant.
+    $this->drupalGet('admin/structure/page_manager/manage/example/page_variant__example-layout_builder-0__layout_builder');
+
+    // Place another block in the first region.
+    $page->find('css', '.layout__region--first .layout-builder__link--add')
+      ->click();
+    $assert_session->assertWaitOnAjaxRequest();
+    $this->clickLink('User account menu');
+    $assert_session->assertWaitOnAjaxRequest();
+    $page->find('css', 'form.layout-builder-add-block .form-submit')->click();
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->pageTextContains('User account menu');
+
+    // Test drag and drop.
+    $page->find('css', '.layout__region--first .menu--account')
+      ->dragTo($page->find('css', '.layout__region--second'));
+    $assert_session->assertWaitOnAjaxRequest();
+
+    // Test contextual links.
+    $assert_session->waitForElement('css', '.block-system-powered-by-block .contextual');
+    $this->clickContextualLink('.block-system-powered-by-block', 'Configure');
+    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas'));
+
+    // Save page.
+    $page->pressButton('Update and save');
+
+    // Check if block is rendered in the correct region.
+    $this->drupalGet('example');
+    $assert_session->waitForElementVisible('css', '.layout__region--first');
+    $assert_session->elementTextContains('css', '.layout__region--first', 'Powered by Drupal');
+    $assert_session->waitForElementVisible('css', '.layout__region--second');
+    $assert_session->elementTextContains('css', '.layout__region--second', 'User account menu');
+  }
+
+}
