diff --git a/core/modules/layout/layout.info b/core/modules/layout/layout.info
new file mode 100644
index 0000000..e6e4a66
--- /dev/null
+++ b/core/modules/layout/layout.info
@@ -0,0 +1,5 @@
+name = Layout
+description = Provide abstract layout handling for html delivering routes.
+package = Core
+version = VERSION
+core = 8.x
diff --git a/core/modules/layout/layout.module b/core/modules/layout/layout.module
new file mode 100644
index 0000000..56f223c
--- /dev/null
+++ b/core/modules/layout/layout.module
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * Implements hook_page_build().
+ */
+function layout_page_build(&$page) {
+  $page['#pre_render'][] = 'layout_page_pre_render';
+}
+
+/**
+ * #pre_render callback for $page.
+ *
+ * @todo Eventually, Drupal routing will be improved so as to replace
+ *   drupal_render_page() (which builds blocks from bottom-up, even if the
+ *   layout instance is not configured to render them) with a top-down
+ *   subrequest workflow. For now, however, we integrate with the
+ *   drupal_render_page() flow, but replace theme('page') with
+ *   $layout->renderLayout().
+ */
+function layout_page_pre_render($page) {
+  $layout = layout_get_layout(drupal_container()->get('request'));
+  if ($layout) {
+    $regions = array();
+    // When drupal_render_page() goes away, so will this, but in the meantime,
+    // this is how we replace page.tpl.php with the layout.
+    $page['#children'] = $layout->renderLayout(FALSE, $regions);
+    $page['#theme'] = NULL;
+  }
+
+  return $page;
+}
+
+function layout_manager() {
+  return drupal_container()->get('plugin.manager.layout');
+}
+
+function layout_get_layout(Request $request) {
+  global $theme;
+  if ($theme == 'bartik') {
+    $conf = array(
+      'regions' => array(
+        'content' => array(
+          'plugin.core.block.bartik.main_content' => array(),
+        ),
+        'help' => array(
+          'plugin.core.block.bartik.help_text' => array(),
+        ),
+        'sidebar_first' => array(
+          'plugin.core.block.bartik.search_form' => array(),
+          'plugin.core.block.bartik.user_login' => array(),
+          //'plugin.core.block.bartik.user_online' => array(),
+          'plugin.core.block.bartik.custom_01' => array(),
+        ),
+        'sidebar_second' => array(
+          'plugin.core.block.bartik.user_menu' => array(),
+        ),
+        'footer' => array(
+          'plugin.core.block.bartik.powered_by' => array(),
+        ),
+      )
+    );
+    $conf['regions']['sidebar_first']['user_online_block'] = array(
+      'subject' => t("Who else is online"),
+      'seconds_online' => 450,
+      'max_list_count' => 5,
+    );
+    return layout_manager()->createInstance('default_layout:bartik__bartik', $conf);
+  }
+}
diff --git a/core/modules/layout/layout/onecol/layout--onecol.tpl.php b/core/modules/layout/layout/onecol/layout--onecol.tpl.php
new file mode 100644
index 0000000..73ad5b8
--- /dev/null
+++ b/core/modules/layout/layout/onecol/layout--onecol.tpl.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * @file
+ * Template for a 3 column panel layout.
+ *
+ * This template provides a very simple "one column" panel display layout.
+ *
+ * Variables:
+ * - $id: An optional CSS id to use for the layout.
+ * - $content: An array of content, each item in the array is keyed to one
+ *   panel of the layout. This layout supports the following sections:
+ *   $content['middle']: The only panel in the layout.
+ */
+?>
+<div class="panel-display panel-1col clearfix" <?php if (!empty($css_id)) { print "id=\"$css_id\""; } ?>>
+  <div class="panel-panel panel-col">
+    <div><?php print $content['middle']; ?></div>
+  </div>
+</div>
diff --git a/core/modules/layout/layout/onecol/onecol.css b/core/modules/layout/layout/onecol/onecol.css
new file mode 100644
index 0000000..83f284a
--- /dev/null
+++ b/core/modules/layout/layout/onecol/onecol.css
@@ -0,0 +1,22 @@
+
+.panel-1col {
+/*  overflow: hidden;  */
+}
+
+.panel-2col .panel-col-first .inside {
+  margin: 0;
+}
+
+
+.panel-1col .panel-col {
+  width: 100%;
+}
+
+#panels-edit-display .panel-pane,
+#panels-edit-display .helperclass {
+  margin: .5em;
+}
+
+.panel-2col .panel-separator {
+  margin: 0 0 1em 0;
+}
diff --git a/core/modules/layout/layout/onecol/onecol.yml b/core/modules/layout/layout/onecol/onecol.yml
new file mode 100644
index 0000000..2ad8959
--- /dev/null
+++ b/core/modules/layout/layout/onecol/onecol.yml
@@ -0,0 +1,6 @@
+title: Single column
+category: Columns: 1
+icon: onecol.png
+css: onecol.css
+regions:
+  middle: 'Middle column'
diff --git a/core/modules/layout/layout/twocol/layout--twocol.tpl.php b/core/modules/layout/layout/twocol/layout--twocol.tpl.php
new file mode 100644
index 0000000..2cda08e
--- /dev/null
+++ b/core/modules/layout/layout/twocol/layout--twocol.tpl.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @file
+ * Template for a 2 column panel layout.
+ *
+ * This template provides a two column panel display layout, with
+ * each column roughly equal in width.
+ *
+ * Variables:
+ * - $id: An optional CSS id to use for the layout.
+ * - $content: An array of content, each item in the array is keyed to one
+ *   panel of the layout. This layout supports the following sections:
+ *   - $content['left']: Content in the left column.
+ *   - $content['right']: Content in the right column.
+ */
+?>
+<div class="panel-display panel-2col clearfix" <?php if (!empty($css_id)) { print "id=\"$css_id\""; } ?>>
+  <div class="panel-panel panel-col-first">
+    <div class="inside"><?php print $content['left']; ?></div>
+  </div>
+
+  <div class="panel-panel panel-col-last">
+    <div class="inside"><?php print $content['right']; ?></div>
+  </div>
+</div>
diff --git a/core/modules/layout/layout/twocol/twocol.css b/core/modules/layout/layout/twocol/twocol.css
new file mode 100644
index 0000000..6e53eca
--- /dev/null
+++ b/core/modules/layout/layout/twocol/twocol.css
@@ -0,0 +1,37 @@
+
+.panel-2col { 
+/*  overflow: hidden;  */
+}
+
+.panel-2col .panel-col-first { 
+  float: left; 
+  width: 50%; 
+}
+* html .panel-2col .panel-col-first {
+  width: 49.9%;
+}
+
+.panel-2col .panel-col-first .inside { 
+  margin: 0 .5em 1em 0;
+}
+
+.panel-2col .panel-col-last { 
+  float: left; 
+  width: 50%; 
+}
+* html .panel-2col .panel-col-last {
+  width: 49.9%;
+}
+
+.panel-2col .panel-col-last .inside { 
+  margin: 0 0 1em .5em;
+}
+
+#panels-edit-display .panel-pane,
+#panels-edit-display .helperclass {
+  margin: .5em;
+}
+
+.panel-2col .panel-separator {
+  margin: 0 0 1em 0;
+}
diff --git a/core/modules/layout/layout/twocol/twocol.yml b/core/modules/layout/layout/twocol/twocol.yml
new file mode 100644
index 0000000..90c4a3e
--- /dev/null
+++ b/core/modules/layout/layout/twocol/twocol.yml
@@ -0,0 +1,7 @@
+title: Two column
+category: Columns: 2
+icon: twocol.png
+css: twocol.css
+regions:
+  left: 'Left side'
+  right: 'Right side'
diff --git a/core/modules/layout/lib/Drupal/layout/LayoutBundle.php b/core/modules/layout/lib/Drupal/layout/LayoutBundle.php
new file mode 100644
index 0000000..1591b6e
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/LayoutBundle.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\layout\LayoutBundle.
+ */
+
+namespace Drupal\Layout;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Layout dependency injection container.
+ */
+class LayoutBundle extends Bundle {
+  /**
+   * Overrides Symfony\Component\HttpKernel\Bundle\Bundle.
+   */
+  public function build(ContainerBuilder $container) {
+    // register the LayoutManager class with the dependency injection container.
+    $container->register('plugin.manager.layout', 'Drupal\layout\Plugin\Type\LayoutManager');
+  }
+}
\ No newline at end of file
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/Derivative/Layout.php b/core/modules/layout/lib/Drupal/layout/Plugin/Derivative/Layout.php
new file mode 100644
index 0000000..a598242
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/Derivative/Layout.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace Drupal\layout\Plugin\Derivative;
+
+use DirectoryIterator;
+use Drupal\Component\Plugin\Derivative\DerivativeInterface;
+use Drupal\Core\Config\FileStorage;
+
+class Layout implements DerivativeInterface {
+  protected $derivatives = array();
+
+  /**
+   * Implements DerivativeInterface::getDerivativeDefinition().
+   */
+  public function getDerivativeDefinition($derivative_id, array $base_plugin_definition) {
+    if (!empty($this->derivatives) && !empty($this->derivatives[$derivative_id])) {
+      return $this->derivatives[$derivative_id];
+    }
+    $this->getDerivativeDefinitions($base_plugin_definition);
+    return $this->derivatives[$derivative_id];
+  }
+
+  /**
+   * Implements DerivativeInterface::getDerivativeDefinitions().
+   */
+  public function getDerivativeDefinitions(array $base_plugin_definition) {
+    $available_layout_providers = array();
+    foreach (module_list() as $module) {
+      $available_layout_providers[$module] = array(
+        'type' => 'module',
+        'provider' => $module,
+        'dir' => drupal_get_path('module', $module),
+      );
+    }
+    foreach (list_themes() as $theme_id => $theme) {
+      $available_layout_providers[$theme_id] = array(
+        'type' => 'theme',
+        'provider' => $theme->name,
+        'dir' => drupal_get_path('theme', $theme->name),
+      );
+    }
+    foreach ($available_layout_providers as $provider) {
+      $dir = $provider['dir'] . DIRECTORY_SEPARATOR . 'layout';
+      // If the directory structure exists, look for layouts.
+      if (file_exists($dir)) {
+        $this->iterateDirectories($dir, $provider);
+      }
+    }
+    return $this->derivatives;
+  }
+
+  protected function iterateDirectories($dir, $provider) {
+    $directories = new DirectoryIterator($dir);
+    foreach ($directories as $fileinfo) {
+      if ($fileinfo->isDir() && !$fileinfo->isDot()) {
+        $this->iterateDirectories($fileinfo->getPathname(), $provider);
+      }
+      elseif ($fileinfo->isFile() && $fileinfo->getExtension() == 'yml') {
+        $directory = new FileStorage($fileinfo->getPath());
+        $this->derivatives[$provider['provider'] . '__' .  $fileinfo->getBasename('.yml')] = $directory->read($fileinfo->getBasename('.yml'));
+        $this->derivatives[$provider['provider'] . '__' .  $fileinfo->getBasename('.yml')]['template'] = $provider['provider'] . '--' .  $fileinfo->getBasename('.yml');
+        $this->derivatives[$provider['provider'] . '__' .  $fileinfo->getBasename('.yml')]['path'] = $fileinfo->getPath();
+      }
+    }
+  }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/LayoutInterface.php b/core/modules/layout/lib/Drupal/layout/Plugin/LayoutInterface.php
new file mode 100644
index 0000000..43410f8
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/LayoutInterface.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Drupal\layout\Plugin;
+
+interface LayoutInterface {
+  public function getRegions();
+
+  public function renderLayout();
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php b/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php
new file mode 100644
index 0000000..386b661
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\layout\Plugin\Type;
+
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator;
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Component\Plugin\Factory\ReflectionFactory;
+
+class LayoutManager extends PluginManagerBase {
+  protected $defaults = array(
+    'class' => 'Drupal\layout\Plugin\layout\layout\DefaultLayout'
+  );
+
+  public function __construct() {
+    $this->discovery = new DerivativeDiscoveryDecorator(new AnnotatedClassDiscovery('layout', 'layout'));
+    $this->factory = new ReflectionFactory($this);
+  }
+}
\ No newline at end of file
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/layout/layout/DefaultLayout.php b/core/modules/layout/lib/Drupal/layout/Plugin/layout/layout/DefaultLayout.php
new file mode 100644
index 0000000..def7fdc
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/layout/layout/DefaultLayout.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace Drupal\layout\Plugin\layout\layout;
+
+use Drupal\layout\Plugin\LayoutInterface;
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Core\Annotation\Plugin;
+
+/**
+ * @Plugin(
+ *  id = "default_layout",
+ *  derivative = "Drupal\layout\Plugin\Derivative\Layout"
+ * )
+ */
+class DefaultLayout extends PluginBase implements LayoutInterface {
+  public function getRegions() {
+    $definition = $this->getDefinition();
+    return $definition['regions'];
+  }
+
+  public function getCss() {
+    $definition = $this->getDefinition();
+    drupal_add_css($definition['path'] . '/' . $definition['css']);
+  }
+
+  public function getAdminCss() {
+    $definition = $this->getDefinition();
+    $css = isset($definition['admin css']) ? $definition['admin css'] : $definition['css'];
+    drupal_add_css($definition['path'] . '/' . $css);
+  }
+
+  public function getJs() {
+    $definition = $this->getDefinition();
+    if (isset($definition['js']))  {
+      drupal_add_js($definition['path'] . '/' . $definition['js']);
+    }
+  }
+
+  // @todo The $regions parameter is here only temporarily. It allows the caller
+  //   to pass already rendered regions, while layout/block configuration code
+  //   is still in progress.
+  public function renderLayout($admin = FALSE, $regions = array()) {
+    $definition = $this->getDefinition();
+
+    // Render all regions not already rendered by the caller.
+    foreach ($this->getRegions() as $region => $title) {
+      if (!isset($regions[$region]) && isset($this->configuration['regions'][$region])) {
+        foreach ($this->configuration['regions'][$region] as $block_id => $configuration) {
+          $block = block_load($block_id, $configuration);
+          if ($block->access()) {
+            // Need to check the caching method on the block to determine exactly
+            // how we're going to get it. Should probably be abstracted out of
+            // this code so that the renderer worries about it instead.
+            $regions[$region][] = array(
+              '#block' => $block,
+              '#theme_wrappers' => array('block'),
+              $block->build()
+            );
+          }
+        }
+        $regions[$region] = drupal_render($regions[$region]);
+      }
+    }
+
+    if (!$admin) {
+      $this->getCss();
+      $this->getJs();
+    }
+    else {
+      $this->getAdminCss();
+    }
+
+    $template = $definition['path'] . '/' . $definition['template'] . '.tpl.php';
+    $output = theme_render_template($template, array('content' => $regions));
+
+    return $output;
+  }
+}
