diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 03d0df0..5a9e1eb 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2512,6 +2512,12 @@ function drupal_common_theme() {
       'variables' => array('display' => NULL),
       'template' => 'status-messages',
     ),
+    // @TODO change this to status_messages once the messages are gone from
+    // template_preprocess_page
+    'status_messages_block' => array(
+      'variables' => array('status_headings' => array(), 'message_list' => NULL),
+      'template' => 'status-messages',
+    ),
     'links' => array(
       'variables' => array('links' => array(), 'attributes' => array('class' => array('links')), 'heading' => array(), 'set_active_class' => FALSE),
       'template' => 'links',
diff --git a/core/modules/system/src/Plugin/Block/SystemPageActionsBlock.php b/core/modules/system/src/Plugin/Block/SystemPageActionsBlock.php
new file mode 100644
index 0000000..3c234a1
--- /dev/null
+++ b/core/modules/system/src/Plugin/Block/SystemPageActionsBlock.php
@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Plugin\Block\SystemPageActionsBlock.
+ */
+
+namespace Drupal\system\Plugin\Block;
+
+use Drupal\block\BlockBase;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Menu\LocalActionManager;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Provides a block to display the page local actions.
+ *
+ * @Block(
+ *   id = "system_page_actions_block",
+ *   admin_label = @Translation("Page actions")
+ * )
+ */
+class SystemPageActionsBlock extends BlockBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * Stores the configuration factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * A local action manger.
+   *
+   * @var \Drupal\Core\Menu\LocalActionManager
+   */
+  protected $localActionManager;
+
+  /**
+   * A request stack object.
+   *
+   * @var \Symfony\Component\HttpFoundation\RequestStack
+   */
+  protected $requestStack;
+
+  /**
+   * Creates a SystemPageActionsBlock instance.
+   *
+   * @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\Config\ConfigFactoryInterface $config_factory
+   *   The factory for configuration objects.
+   * @param \Drupal\Core\Menu\LocalActionManager $local_action_manager
+   *   The local action manager.
+   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
+   *   The request stack object.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory, LocalActionManager $local_action_manager, RequestStack $request_stack) {
+      parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configFactory = $config_factory;
+    $this->localActionManager = $local_action_manager;
+    $this->requestStack = $request_stack;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('config.factory'),
+      $container->get('plugin.manager.menu.local_action'),
+      $container->get('request_stack')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return array(
+      'label_display' => FALSE,
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build() {
+    $build = array();
+    $links = menu_local_tasks();
+    $request = $this->requestStack->getCurrentRequest();
+    $route_name = $request->attributes->get(RouteObjectInterface::ROUTE_NAME);
+    $action_links = $this->localActionManager->getActionsForRoute($route_name) + $links['actions'];
+
+    $build['action_links'] = array(
+      '#markup' => $action_links,
+    );
+
+    return $build;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, array &$form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
+
+    // The page actions block is never cacheable, because it may be dynamic.
+    $form['cache']['#disabled'] = TRUE;
+    $form['cache']['#description'] = $this->t('This block is never cacheable, it is not configurable.');
+    $form['cache']['max_age']['#value'] = 0;
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isCacheable() {
+    // The page actions block is never cacheable, because it may be dynamic.
+    return FALSE;
+  }
+
+}
diff --git a/core/modules/system/src/Plugin/Block/SystemPageMessagesBlock.php b/core/modules/system/src/Plugin/Block/SystemPageMessagesBlock.php
new file mode 100644
index 0000000..202f203
--- /dev/null
+++ b/core/modules/system/src/Plugin/Block/SystemPageMessagesBlock.php
@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Plugin\Block\SystemPageMessagesBlock.
+ */
+
+namespace Drupal\system\Plugin\Block;
+
+use Drupal\block\BlockBase;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a block to display the page messages.
+ *
+ * @Block(
+ *   id = "system_page_messages_block",
+ *   admin_label = @Translation("Page messages")
+ * )
+ */
+class SystemPageMessagesBlock extends BlockBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * Stores the configuration factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * The messages.
+   * They are stored in a static property so they can appear in multiple blocks.
+   *
+   */
+  protected static $messages;
+
+  /**
+   * Creates a SystemPageMessagesBlock instance.
+   *
+   * @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\Config\ConfigFactoryInterface $config_factory
+   *   The factory for configuration objects.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configFactory = $config_factory;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('config.factory')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return array(
+      'label_display' => FALSE,
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build() {
+
+    $build['messages'] = array(
+      // @TODO change this to status_messages once the messages are gone from
+      // template_preprocess_page
+      '#theme' => 'status_messages_block',
+      '#pre_render' => array(array($this, 'getMessages')),
+    );
+    $build['messages']['#status_headings'] = array(
+      'status' => t('Status message'),
+      'error' => t('Error message'),
+      'warning' => t('Warning message'),
+    );
+
+    return $build;
+  }
+
+  /**
+   * Gets messages in the pre-render stage.
+   *
+   * @param $element
+   * @return mixed
+   */
+  public function getMessages($element) {
+    if (!isset(static::$messages)) {
+      static::$messages = drupal_get_messages();
+    }
+    $element['#message_list'] = static::$messages;
+    return $element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, array &$form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
+
+    // The page messages block is never cacheable, because it may be dynamic.
+    $form['cache']['#disabled'] = TRUE;
+    $form['cache']['#description'] = $this->t('This block is never cacheable, it is not configurable.');
+    $form['cache']['max_age']['#value'] = 0;
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isCacheable() {
+    // The page messages block is never cacheable, because it may be dynamic.
+    return FALSE;
+  }
+
+}
diff --git a/core/modules/system/src/Plugin/Block/SystemPageTabsBlock.php b/core/modules/system/src/Plugin/Block/SystemPageTabsBlock.php
new file mode 100644
index 0000000..67e737b
--- /dev/null
+++ b/core/modules/system/src/Plugin/Block/SystemPageTabsBlock.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Plugin\Block\SystemPageTabsBlock.
+ */
+
+namespace Drupal\system\Plugin\Block;
+
+use Drupal\block\BlockBase;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a block to display the page tabs.
+ *
+ * @Block(
+ *   id = "system_page_tabs_block",
+ *   admin_label = @Translation("Page tabs")
+ * )
+ */
+class SystemPageTabsBlock extends BlockBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * Stores the configuration factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * Creates a SystemPageTabsBlock instance.
+   *
+   * @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\Config\ConfigFactoryInterface $config_factory
+   *   The factory for configuration objects.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory) {
+      parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configFactory = $config_factory;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('config.factory')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return array(
+      'label_display' => FALSE,
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build() {
+    $build['tabs']['#markup'] = menu_local_tabs();
+    return $build;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, array &$form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
+
+    // The page tabs block is never cacheable, because it may be dynamic.
+    $form['cache']['#disabled'] = TRUE;
+    $form['cache']['#description'] = $this->t('This block is never cacheable, it is not configurable.');
+    $form['cache']['max_age']['#value'] = 0;
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isCacheable() {
+    // The page tabs block is never cacheable, because it may be dynamic.
+    return FALSE;
+  }
+
+}
diff --git a/core/modules/system/src/Plugin/Block/SystemPageTitleBlock.php b/core/modules/system/src/Plugin/Block/SystemPageTitleBlock.php
new file mode 100644
index 0000000..a198c0c
--- /dev/null
+++ b/core/modules/system/src/Plugin/Block/SystemPageTitleBlock.php
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Plugin\Block\SystemPageTitleBlock.
+ */
+
+namespace Drupal\system\Plugin\Block;
+
+use Drupal\block\BlockBase;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Controller\TitleResolverInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Provides a block to display the page title.
+ *
+ * @Block(
+ *   id = "system_page_title_block",
+ *   admin_label = @Translation("Page title")
+ * )
+ */
+class SystemPageTitleBlock extends BlockBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * Stores the configuration factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * The title resolver.
+   *
+   * @var \Drupal\Core\Controller\TitleResolverInterface
+   */
+  protected $titleResolver;
+
+  /**
+   * A request stack object.
+   *
+   * @var \Symfony\Component\HttpFoundation\RequestStack
+   */
+  protected $requestStack;
+
+  /**
+   * Creates a SystemPageTitleBlock instance.
+   *
+   * @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\Config\ConfigFactoryInterface $config_factory
+   *   The factory for configuration objects.
+   * @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
+   *   The title resolver.
+   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
+   *   The request stack object.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory, TitleResolverInterface $title_resolver, RequestStack $request_stack) {
+      parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configFactory = $config_factory;
+    $this->titleResolver = $title_resolver;
+    $this->requestStack = $request_stack;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('config.factory'),
+      $container->get('title_resolver'),
+      $container->get('request_stack')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return array(
+      'label_display' => FALSE,
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build() {
+    $build = array();
+    $title = '';
+    $request = $this->requestStack->getCurrentRequest();
+    if ($route = $request->attributes->get(routeObjectInterface::ROUTE_OBJECT)) {
+      $title = $this->titleResolver->getTitle($request, $route);
+    }
+
+    $build['title'] = array(
+      '#markup' => $title,
+    );
+
+    return $build;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, array &$form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
+
+    // The page title block is never cacheable, because it may be dynamic.
+    $form['cache']['#disabled'] = TRUE;
+    $form['cache']['#description'] = $this->t('This block is never cacheable, it is not configurable.');
+    $form['cache']['max_age']['#value'] = 0;
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isCacheable() {
+    // The page title block is never cacheable, because it may be dynamic.
+    return FALSE;
+  }
+
+}
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index ac44ab5..f703fd1 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -160,13 +160,28 @@ function system_help($route_name, Request $request) {
 function system_theme() {
   return array_merge(drupal_common_theme(), array(
     // Normally theme suggestion templates are only picked up when they are in
-    // themes. We explicitly define the block__system_branding_block theme
-    // suggestion here so that the template in core/modules/system/templates
-    // is picked up.
+    // themes. We explicitly define theme suggestions here so that the
+    // block templates in core/modules/system/templates are picked up.
     'block__system_branding_block' => array(
       'base hook' => 'block',
       'template' => 'block--system-branding-block',
     ),
+    'block__system_page_title_block' => array(
+      'base hook' => 'block',
+      'template' => 'block--system-page-title-block',
+    ),
+    'block__system_page_actions_block' => array(
+      'base hook' => 'block',
+      'template' => 'block--system-page-actions-block',
+    ),
+    'block__system_page_tabs_block' => array(
+      'base hook' => 'block',
+      'template' => 'block--system-page-tabs-block',
+    ),
+    'block__system_page_messages_block' => array(
+      'base hook' => 'block',
+      'template' => 'block--system-page-messages-block',
+    ),
     'system_themes_page' => array(
       'variables' => array(
         'theme_groups' => array(),
@@ -1072,6 +1087,27 @@ function system_preprocess_block(&$variables) {
       }
       break;
 
+    case 'system_page_title_block':
+      $variables['title'] = '';
+      if($variables['content']['title']['#markup']) {
+        $variables['title'] = $variables['content']['title']['#markup'];
+      }
+      break;
+
+    case 'system_page_actions_block':
+      $variables['action_links'] = '';
+      if($variables['content']['action_links']['#markup']) {
+        $variables['action_links'] = $variables['content']['action_links']['#markup'];
+      }
+      break;
+
+    case 'system_page_tabs_block':
+      $variables['tabs'] = '';
+      if($variables['content']['tabs']['#markup']) {
+        $variables['tabs'] = $variables['content']['tabs']['#markup'];
+      }
+      break;
+
     case 'system_powered_by_block':
       $variables['attributes']['role'] = 'complementary';
       break;
diff --git a/core/modules/system/templates/block--system-page-actions-block.html.twig b/core/modules/system/templates/block--system-page-actions-block.html.twig
new file mode 100644
index 0000000..a5972dc
--- /dev/null
+++ b/core/modules/system/templates/block--system-page-actions-block.html.twig
@@ -0,0 +1,18 @@
+{% extends "@block/block.html.twig" %}
+{#
+/**
+ * @file
+ * Default theme implementation for page local actions.
+ *
+ * Available variables:
+ * - action_links: Actions local to the page, such as "Add menu" on the menu
+ *   administration interface.
+ *
+ * @ingroup themeable
+ */
+#}
+{% block content %}
+  {% if action_links %}
+    <nav class="action-links">{{ action_links }}</nav>
+  {% endif %}
+{% endblock %}
diff --git a/core/modules/system/templates/block--system-page-messages-block.html.twig b/core/modules/system/templates/block--system-page-messages-block.html.twig
new file mode 100644
index 0000000..55175d7
--- /dev/null
+++ b/core/modules/system/templates/block--system-page-messages-block.html.twig
@@ -0,0 +1,15 @@
+{#
+/**
+ * @file
+ * Default theme implementation for page messages.
+ *
+ * Removes wrapper elements from block so that empty block does not appear when
+ * there are no messages.
+ *
+ * Available variables:
+ * - content: The content of this block.
+ *
+ * @ingroup themeable
+ */
+#}
+{{ content }}
diff --git a/core/modules/system/templates/block--system-page-tabs-block.html.twig b/core/modules/system/templates/block--system-page-tabs-block.html.twig
new file mode 100644
index 0000000..780abe7
--- /dev/null
+++ b/core/modules/system/templates/block--system-page-tabs-block.html.twig
@@ -0,0 +1,16 @@
+{% extends "@block/block.html.twig" %}
+{#
+/**
+ * @file
+ * Default theme implementation for page tabs.
+ *
+ * Available variables:
+ * - tabs: The Tabs linking to any sub-pages beneath the current page (e.g., the
+ *   view and edit tabs when displaying a node).
+ *
+ * @ingroup themeable
+ */
+#}
+{% block content %}
+  {{ tabs }}
+{% endblock %}
diff --git a/core/modules/system/templates/block--system-page-title-block.html.twig b/core/modules/system/templates/block--system-page-title-block.html.twig
new file mode 100644
index 0000000..aca427c
--- /dev/null
+++ b/core/modules/system/templates/block--system-page-title-block.html.twig
@@ -0,0 +1,23 @@
+{% extends "@block/block.html.twig" %}
+{#
+/**
+ * @file
+ * Default theme implementation for a page title.
+ *
+ * Available variables:
+ * - title_prefix: Additional output populated by modules, intended to be
+ *   displayed in front of the main title tag that appears in the template.
+ * - title: The page title, for use in the actual content.
+ * - title_suffix: Additional output populated by modules, intended to be
+ *   displayed after the main title tag that appears in the template.
+ *
+ * @ingroup themeable
+ */
+#}
+{% block content %}
+  {{ title_prefix }}
+  {% if title %}
+    <h1>{{ title }}</h1>
+  {% endif %}
+  {{ title_suffix }}
+{% endblock %}
diff --git a/core/themes/bartik/templates/block--system-page-actions-block.html.twig b/core/themes/bartik/templates/block--system-page-actions-block.html.twig
new file mode 100644
index 0000000..b8283b5
--- /dev/null
+++ b/core/themes/bartik/templates/block--system-page-actions-block.html.twig
@@ -0,0 +1,20 @@
+{% extends "@block/block.html.twig" %}
+{#
+/**
+ * @file
+ * Bartik's theme implementation for page local actions.
+ *
+ * Available variables:
+ * - action_links: Actions local to the page, such as "Add menu" on the menu
+ *   administration interface.
+ *
+ * @ingroup themeable
+ */
+#}
+{% block content %}
+  {% if action_links %}
+    <ul class="action-links">
+      {{ action_links }}
+    </ul>
+  {% endif %}
+{% endblock %}
diff --git a/core/themes/bartik/templates/block--system-page-tabs-block.html.twig b/core/themes/bartik/templates/block--system-page-tabs-block.html.twig
new file mode 100644
index 0000000..429ad98
--- /dev/null
+++ b/core/themes/bartik/templates/block--system-page-tabs-block.html.twig
@@ -0,0 +1,20 @@
+{% extends "@block/block.html.twig" %}
+{#
+/**
+ * @file
+ * Bartik's theme implementation for page tabs.
+ *
+ * Available variables:
+ * - tabs: The Tabs linking to any sub-pages beneath the current page (e.g., the
+ *   view and edit tabs when displaying a node).
+ *
+ * @ingroup themeable
+ */
+#}
+{% block content %}
+  {% if tabs %}
+     <nav class="tabs" role="navigation" aria-label="{{ 'Tabs'|t }}">
+       {{ tabs }}
+     </nav>
+  {% endif %}
+{% endblock %}
diff --git a/core/themes/bartik/templates/block--system-page-title-block.html.twig b/core/themes/bartik/templates/block--system-page-title-block.html.twig
new file mode 100644
index 0000000..4bd27f1
--- /dev/null
+++ b/core/themes/bartik/templates/block--system-page-title-block.html.twig
@@ -0,0 +1,25 @@
+{% extends "@block/block.html.twig" %}
+{#
+/**
+ * @file
+ * Bartik's theme implementation for a page title.
+ *
+ * Available variables:
+ * - title_prefix: Additional output populated by modules, intended to be
+ *   displayed in front of the main title tag that appears in the template.
+ * - title: The page title, for use in the actual content.
+ * - title_suffix: Additional output populated by modules, intended to be
+ *   displayed after the main title tag that appears in the template.
+ *
+ * @ingroup themeable
+ */
+#}
+{% block content %}
+  {{ title_prefix }}
+  {% if title %}
+    <h1 class="title" id="page-title">
+      {{ title }}
+    </h1>
+  {% endif %}
+  {{ title_suffix }}
+{% endblock %}
diff --git a/core/themes/bartik/templates/page.html.twig b/core/themes/bartik/templates/page.html.twig
index 8c739bb..b8883cc 100644
--- a/core/themes/bartik/templates/page.html.twig
+++ b/core/themes/bartik/templates/page.html.twig
@@ -131,9 +131,7 @@
   </div></header> <!-- /.section, /#header-->
 
   {% if messages %}
-    <div id="messages"><div class="section clearfix">
-      {{ messages }}
-    </div></div> <!-- /.section, /#messages -->
+    {{ messages }}
   {% endif %}
 
   {% if page.featured %}
diff --git a/core/themes/bartik/templates/status-messages.html.twig b/core/themes/bartik/templates/status-messages.html.twig
new file mode 100644
index 0000000..87b8dcd
--- /dev/null
+++ b/core/themes/bartik/templates/status-messages.html.twig
@@ -0,0 +1,58 @@
+{#
+/**
+ * @file
+ * Default theme implementation for status messages.
+ *
+ * Displays status, error, and warning messages, grouped by type.
+ *
+ * An invisible heading identifies the messages for assistive technology.
+ * Sighted users see a colored box. See http://www.w3.org/TR/WCAG-TECHS/H69.html
+ * for info.
+ *
+ * Add an ARIA label to the contentinfo area so that assistive technology
+ * user agents will better describe this landmark.
+ *
+ * Available variables:
+ * - message_list: List of messages to be displayed, grouped by type.
+ * - status_headings: List of all status types.
+ * - display: (optional) May have a value of 'status' or 'error' when only
+ *   displaying messages of that specific type.
+ *
+ * @see template_preprocess_status_messages()
+ *
+ * @ingroup themeable
+ */
+#}
+{% set has_messages = 0 %}
+{% for type, messages in message_list %}
+  {% if messages|length > 0 %}
+    {% set has_messages = 1 %}
+  {% endif %}
+{% endfor %}
+
+{% if has_messages %}
+<div id="messages"><div class="section clearfix">
+{% for type, messages in message_list %}
+  <div class="messages messages--{{ type }}" role="contentinfo" aria-label="{{ status_headings[type] }}">
+    {% if type == 'error' %}
+      <div role="alert">
+    {% endif %}
+      {% if status_headings[type] %}
+        <h2 class="visually-hidden">{{ status_headings[type] }}</h2>
+      {% endif %}
+      {% if messages|length > 1 %}
+        <ul class="messages__list">
+          {% for message in messages %}
+            <li class="messages__item">{{ message }}</li>
+          {% endfor %}
+        </ul>
+      {% else %}
+        {{ messages.0 }}
+      {% endif %}
+    {% if type == 'error' %}
+      </div>
+    {% endif %}
+  </div>
+{% endfor %}
+</div></div> <!-- /.section, /#messages -->
+{% endif %}
