diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 3483330..3dc750e 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -9,8 +9,11 @@
  */
 
 use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Config\Config;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Utility\ThemeRegistry;
+use Drupal\Core\Theme\ThemeSettings;
 
 /**
  * @defgroup content_flags Content markers
@@ -1356,7 +1359,6 @@ function drupal_find_theme_templates($cache, $extension, $path) {
  *
  * The final setting is obtained from the last value found in the following
  * sources:
- * - the default global settings specified in this function
  * - the default theme-specific settings defined in any base theme's .info file
  * - the default theme-specific settings defined in the theme's .info file
  * - the saved values from the global theme settings form
@@ -1381,23 +1383,8 @@ function theme_get_setting($setting_name, $theme = NULL) {
   }
 
   if (empty($cache[$theme])) {
-    // Set the default values for each global setting.
-    // To add new global settings, add their default values below, and then
-    // add form elements to system_theme_settings() in system.admin.inc.
-    $cache[$theme] = array(
-      'default_logo'                     =>  1,
-      'logo_path'                        =>  '',
-      'default_favicon'                  =>  1,
-      'favicon_path'                     =>  '',
-      // Use the IANA-registered MIME type for ICO files as default.
-      'favicon_mimetype'                 =>  'image/vnd.microsoft.icon',
-    );
-    // Turn on all default features.
-    $features = _system_default_theme_features();
-    foreach ($features as $feature) {
-      $cache[$theme]['toggle_' . $feature] = 1;
-    }
-
+    // Create a theme settings object.
+    $cache[$theme] = new ThemeSettings($theme);
     // Get the values for the theme-specific settings from the .info files of
     // the theme and all its base themes.
     if ($theme) {
@@ -1414,62 +1401,111 @@ function theme_get_setting($setting_name, $theme = NULL) {
       }
       foreach ($theme_keys as $theme_key) {
         if (!empty($themes[$theme_key]->info['settings'])) {
-          $cache[$theme] = array_merge($cache[$theme], $themes[$theme_key]->info['settings']);
+          $cache[$theme]->setData(NestedArray::mergeDeep($cache[$theme]->get(), $themes[$theme_key]->info['settings']));
         }
       }
     }
 
-    // Get the saved global settings from the database.
-    $cache[$theme] = array_merge($cache[$theme], variable_get('theme_settings', array()));
+    // Get the global settings from configuration.
+    $cache[$theme]->setData(NestedArray::mergeDeep($cache[$theme]->get(), config('system.theme.global')->get()));
 
     if ($theme) {
-      // Get the saved theme-specific settings from the database.
-      $cache[$theme] = array_merge($cache[$theme], variable_get('theme_' . $theme . '_settings', array()));
+      // Get the saved theme-specific settings from the configuration system.
+      $cache[$theme]->setData(NestedArray::mergeDeep($cache[$theme]->get(), config($theme . '.settings')->get()));
 
       // If the theme does not support a particular feature, override the global
       // setting and set the value to NULL.
+      //$supports = $cache[$theme]->get('supports');
       if (!empty($theme_object->info['features'])) {
-        foreach ($features as $feature) {
+        foreach (_system_default_theme_features() as $feature) {
           if (!in_array($feature, $theme_object->info['features'])) {
-            $cache[$theme]['toggle_' . $feature] = NULL;
+            $cache[$theme]->set('features.' . $feature, NULL);
           }
         }
       }
 
       // Generate the path to the logo image.
-      if ($cache[$theme]['toggle_logo']) {
-        if ($cache[$theme]['default_logo']) {
-          $cache[$theme]['logo'] = file_create_url(dirname($theme_object->filename) . '/logo.png');
+      if ($cache[$theme]->get('features.logo')) {
+        $logo_path = $cache[$theme]->get('logo.path');
+        if ($cache[$theme]->get('logo.use_default')) {
+          $cache[$theme]->set('logo.url', file_create_url(dirname($theme_object->filename) . '/logo.png'));
         }
-        elseif ($cache[$theme]['logo_path']) {
-          $cache[$theme]['logo'] = file_create_url($cache[$theme]['logo_path']);
+        elseif ($logo_path) {
+          $cache[$theme]->set('logo.url', file_create_url($logo_path));
         }
       }
 
       // Generate the path to the favicon.
-      if ($cache[$theme]['toggle_favicon']) {
-        if ($cache[$theme]['default_favicon']) {
+      if ($cache[$theme]->get('features.favicon')) {
+        $favicon_path = $cache[$theme]->get('favicon.path');
+        if ($cache[$theme]->get('favicon.use_default')) {
           if (file_exists($favicon = dirname($theme_object->filename) . '/favicon.ico')) {
-            $cache[$theme]['favicon'] = file_create_url($favicon);
+            $cache[$theme]->set('favicon.url', file_create_url($favicon));
           }
           else {
-            $cache[$theme]['favicon'] = file_create_url('core/misc/favicon.ico');
+            $cache[$theme]->set('favicon.url', file_create_url('core/misc/favicon.ico'));
           }
         }
-        elseif ($cache[$theme]['favicon_path']) {
-          $cache[$theme]['favicon'] = file_create_url($cache[$theme]['favicon_path']);
+        elseif ($favicon_path) {
+          $cache[$theme]->set('favicon.url', file_create_url($favicon_path));
         }
         else {
-          $cache[$theme]['toggle_favicon'] = FALSE;
+          $cache[$theme]->set('features.favicon', FALSE);
         }
       }
     }
   }
 
-  return isset($cache[$theme][$setting_name]) ? $cache[$theme][$setting_name] : NULL;
+  return $cache[$theme]->get($setting_name);
 }
 
 /**
+ * Converts format of old theme-configuration to the format of yml-configuration.
+ *
+ * @todo D8: Move this function to update.inc after updating the theme settings
+ * form to use the new configuration object keys.
+ *
+ * @param array $theme_settings
+ *   An array of theme settings from system setting form or a Drupal 7 variable.
+ * @param Config $config
+ *   The configuration object to update.
+ *
+ * @return
+ *   The Config object with updated data.
+ */
+function theme_settings_convert_to_config(array $theme_settings, Config $config) {
+  foreach ($theme_settings as $key => $value) {
+    if ($key == 'logo') {
+      $config->set('logo.url', $value);
+    }
+    else if ($key == 'default_logo') {
+      $config->set('logo.use_default', $value);
+    }
+    else if ($key == 'logo_path') {
+      $config->set('logo.path', $value);
+    }
+    else if ($key == 'favicon') {
+      $config->set('favicon.url', $value);
+    }
+    else if ($key == 'default_favicon') {
+      $config->set('favicon.use_default', $value);
+    }
+    else if ($key == 'favicon_path') {
+      $config->set('favicon.path', $value);
+    }
+    else if ($key == 'favicon_mimetype') {
+      $config->set('favicon.mimetype', $value);
+    }
+    else if (substr($key, 0, 7) == 'toggle_') {
+      $config->set('features.' . drupal_substr($key, 7), $value);
+    }
+    else if (!in_array($key, array('theme', 'logo_upload'))) {
+      $config->set($key, $value);
+    }
+  }
+  return $config;
+}
+/**
  * Renders a system default template, which is essentially a PHP template.
  *
  * @param $template_file
@@ -2723,9 +2759,9 @@ function template_preprocess_html(&$variables) {
   $variables['html_attributes']['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
 
   // Add favicon.
-  if (theme_get_setting('toggle_favicon')) {
-    $favicon = theme_get_setting('favicon');
-    $type = theme_get_setting('favicon_mimetype');
+  if (theme_get_setting('features.favicon')) {
+    $favicon = theme_get_setting('favicon.url');
+    $type = theme_get_setting('favicon.mimetype');
     drupal_add_html_head_link(array('rel' => 'shortcut icon', 'href' => drupal_strip_dangerous_protocols($favicon), 'type' => $type));
   }
 
@@ -2831,12 +2867,12 @@ function template_preprocess_page(&$variables) {
   $variables['feed_icons']        = drupal_get_feeds();
   $variables['language']          = $language_interface;
   $variables['language']->dir     = $language_interface->direction ? 'rtl' : 'ltr';
-  $variables['logo']              = theme_get_setting('logo');
-  $variables['main_menu']         = theme_get_setting('toggle_main_menu') ? menu_main_menu() : array();
-  $variables['secondary_menu']    = theme_get_setting('toggle_secondary_menu') ? menu_secondary_menu() : array();
+  $variables['logo']              = theme_get_setting('logo.url');
+  $variables['main_menu']         = theme_get_setting('features.main_menu') ? menu_main_menu() : array();
+  $variables['secondary_menu']    = theme_get_setting('features.secondary_menu') ? menu_secondary_menu() : array();
   $variables['action_links']      = menu_local_actions();
-  $variables['site_name']         = (theme_get_setting('toggle_name') ? check_plain($site_config->get('name')) : '');
-  $variables['site_slogan']       = (theme_get_setting('toggle_slogan') ? filter_xss_admin($site_config->get('slogan')) : '');
+  $variables['site_name']         = (theme_get_setting('features.name') ? check_plain($site_config->get('name')) : '');
+  $variables['site_slogan']       = (theme_get_setting('features.slogan') ? filter_xss_admin($site_config->get('slogan')) : '');
   $variables['tabs']              = menu_local_tabs();
 
   if ($node = menu_get_object()) {
@@ -2995,9 +3031,9 @@ function template_preprocess_maintenance_page(&$variables) {
   $regions = $theme_data[$theme]->info['regions'];
 
   // Add favicon
-  if (theme_get_setting('toggle_favicon')) {
-    $favicon = theme_get_setting('favicon');
-    $type = theme_get_setting('favicon_mimetype');
+  if (theme_get_setting('features.favicon')) {
+    $favicon = theme_get_setting('favicon.url');
+    $type = theme_get_setting('favicon.mimetype');
     drupal_add_html_head_link(array('rel' => 'shortcut icon', 'href' => drupal_strip_dangerous_protocols($favicon), 'type' => $type));
   }
 
@@ -3044,12 +3080,12 @@ function template_preprocess_maintenance_page(&$variables) {
   $variables['help']              = '';
   $variables['language']          = $language_interface;
   $variables['language']->dir     = $language_interface->direction ? 'rtl' : 'ltr';
-  $variables['logo']              = theme_get_setting('logo');
+  $variables['logo']              = theme_get_setting('logo.url');
   $variables['messages']          = $variables['show_messages'] ? theme('status_messages') : '';
   $variables['main_menu']         = array();
   $variables['secondary_menu']    = array();
-  $variables['site_name']         = (theme_get_setting('toggle_name') ? check_plain($site_name) : '');
-  $variables['site_slogan']       = (theme_get_setting('toggle_slogan') ? filter_xss_admin($site_slogan) : '');
+  $variables['site_name']         = (theme_get_setting('features.name') ? check_plain($site_name) : '');
+  $variables['site_slogan']       = (theme_get_setting('features.slogan') ? filter_xss_admin($site_slogan) : '');
   $variables['tabs']              = '';
   $variables['title']             = drupal_get_title();
 
diff --git a/core/includes/update.inc b/core/includes/update.inc
index 24f8b47..3055ce8 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -1441,7 +1441,42 @@ function update_config_manifest_add($config_prefix, array $ids) {
 }
 
 /**
- * Updates 7.x variables to state records.
+ * Installs a default configuration file into the active store.
+ *
+ * Provide a generalised method to save a default configuration object for an
+ * already enabled module or theme as part of an update from Drupal 7 to Drupal
+ * 8's configuration management system.
+ *
+ * @param string $type
+ *   The extension type; e.g., 'module' or 'theme'.
+ * @param string $config_name
+ *   The configuration object name to retrieve.
+ *
+ * @return boolean
+ *   True on success, false if config file does not exist.
+ */
+function update_7_to_8_install_default_config($type, $config_name) {
+  // Build the new configuration object.
+  $config = config($config_name);
+
+  // Extract the extension namespace/owner from the configuration object name.
+  $name = strtok($config_name, '.');
+
+  // Load and set default configuration values.
+  $file = new FileStorage(drupal_get_path($type, $name) . '/config');
+  if (!$file->exists($config_name)) {
+    return FALSE;
+  }
+  $default_data = $file->read($config_name);
+  // Apply and save the default values.
+  $config->setData($file->read($config_name))->save();
+  return TRUE;
+}
+
+/**
+ * @defgroup update-api-7.x-to-8.x Update versions of API functions
+ * @{
+ * Functions similar to normal API function but not firing hooks.
  *
  * Provides a generalized method to migrate variables from 7.x to 8.x's
  * state() system.
diff --git a/core/lib/Drupal/Core/Theme/ThemeSettings.php b/core/lib/Drupal/Core/Theme/ThemeSettings.php
new file mode 100644
index 0000000..a596ed7
--- /dev/null
+++ b/core/lib/Drupal/Core/Theme/ThemeSettings.php
@@ -0,0 +1,146 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Theme\ThemeSettings.
+ */
+
+namespace Drupal\Core\Theme;
+
+use Drupal\Component\Utility\NestedArray;
+
+/**
+ * Defines the default theme settings object.
+ */
+class ThemeSettings {
+
+  /**
+   * The theme of the theme settings object.
+   *
+   * @var string
+   */
+  protected $theme;
+
+  /**
+   * The data of the theme settings object.
+   *
+   * @var array
+   */
+  protected $data;
+
+  /**
+   * Constructs a theme settings object.
+   *
+   * @param string $name
+   *   The name of the theme settings object being constructed.
+   */
+  public function __construct($theme) {
+    $this->theme = $theme;
+    $this->data = array();
+  }
+
+  /**
+   * Returns the theme of this theme settings object.
+   *
+   * @return string
+   *   The theme of this theme settings object.
+   */
+  public function getTheme() {
+    return $this->theme;
+  }
+
+  /**
+   * Gets data from this theme settings object.
+   *
+   * @param string $key
+   *   A string that maps to a key within the theme settings data.
+   *   For instance in the following theme settings array:
+   *   @code
+   *   array(
+   *     'foo' => array(
+   *       'bar' => 'baz',
+   *     ),
+   *   );
+   *   @endcode
+   *   A key of 'foo.bar' would return the string 'baz'. However, a key of 'foo'
+   *   would return array('bar' => 'baz').
+   *   If no key is specified, then the entire data array is returned.
+   *
+   *
+   * @return mixed
+   *   The data that was requested.
+   */
+  public function get($key = '') {
+    if (empty($key)) {
+      return $this->data;
+    }
+    else {
+      $parts = explode('.', $key);
+      if (count($parts) == 1) {
+        return isset($this->data[$key]) ? $this->data[$key] : NULL;
+      }
+      else {
+        $value = NestedArray::getValue($this->data, $parts, $key_exists);
+        return $key_exists ? $value : NULL;
+      }
+    }
+  }
+
+  /**
+   * Replaces the data of this theme settings object.
+   *
+   * @param array $data
+   *   The new theme settings data.
+   *
+   * @return Drupal\Core\Theme\ThemeSettings
+   *   The theme settings object.
+   */
+  public function setData(array $data) {
+    $this->data = $data;
+    return $this;
+  }
+
+  /**
+   * Sets value in this theme settings object.
+   *
+   * @param string $key
+   *   Identifier to store value in theme settings.
+   * @param string $value
+   *   Value to associate with identifier.
+   *
+   * @return Drupal\Core\Theme\ThemeSettings
+   *   The theme settings object.
+   */
+  public function set($key, $value) {
+    // The dot/period is a reserved character; it may appear between keys, but
+    // not within keys.
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      $this->data[$key] = $value;
+    }
+    else {
+      NestedArray::setValue($this->data, $parts, $value);
+    }
+    return $this;
+  }
+
+  /**
+   * Unsets value in this theme settings object.
+   *
+   * @param string $key
+   *   Name of the key whose value should be unset.
+   *
+   * @return Drupal\Core\Theme\ThemeSettings
+   *   The theme settings object.
+   */
+  public function clear($key) {
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      unset($this->data[$key]);
+    }
+    else {
+      NestedArray::unsetValue($this->data, $parts);
+    }
+    return $this;
+  }
+}
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 6f2795a..15c6189 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1641,7 +1641,7 @@ function template_preprocess_comment(&$variables) {
     $variables['changed'] = format_date($comment->changed->value);
   }
 
-  if (theme_get_setting('toggle_comment_user_picture')) {
+  if (theme_get_setting('features.comment_user_picture')) {
     // To change user picture settings (e.g., image style), edit the 'compact'
     // view mode on the User entity.
     $variables['user_picture'] = user_view($account, 'compact');
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index ff073ae..8311092 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1179,7 +1179,7 @@ function template_preprocess_node(&$variables) {
   if (variable_get('node_submitted_' . $node->type, TRUE)) {
     $variables['display_submitted'] = TRUE;
     $variables['submitted'] = t('Submitted by !username on !datetime', array('!username' => $variables['name'], '!datetime' => $variables['date']));
-    if (theme_get_setting('toggle_node_user_picture')) {
+    if (theme_get_setting('features.node_user_picture')) {
       // To change user picture settings (e.g. image style), edit the 'compact'
       // view mode on User entity.
       $variables['user_picture'] = user_view($node->account, 'compact');
diff --git a/core/modules/system/config/system.theme.global.yml b/core/modules/system/config/system.theme.global.yml
new file mode 100644
index 0000000..2d5bc35
--- /dev/null
+++ b/core/modules/system/config/system.theme.global.yml
@@ -0,0 +1,19 @@
+favicon:
+  mimetype: image/vnd.microsoft.icon
+  path: ''
+  url: ''
+  use_default: '1'
+features:
+  comment_user_picture: '1'
+  comment_user_verification: '1'
+  favicon: '1'
+  logo: '1'
+  name: '1'
+  node_user_picture: '1'
+  main_menu: '1'
+  secondary_menu: '1'
+  slogan: '1'
+logo:
+  path: ''
+  url: ''
+  use_default: '1'
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 6583d57..ee4ebc9 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -386,20 +386,24 @@ function system_theme_default() {
  * @return
  *   The form structure.
  * @ingroup forms
+ * @see system_theme_settings_validate()
  * @see system_theme_settings_submit()
  */
 function system_theme_settings($form, &$form_state, $key = '') {
   // Default settings are defined in theme_get_setting() in includes/theme.inc
   if ($key) {
     $var = 'theme_' . $key . '_settings';
+    $config_key = $key . '.settings';
     $themes = list_themes();
     $features = $themes[$key]->info['features'];
   }
   else {
     $var = 'theme_settings';
+    $config_key = 'system.theme.global';
   }
 
   $form['var'] = array('#type' => 'hidden', '#value' => $var);
+  $form['config_key'] = array('#type' => 'hidden', '#value' => $config_key);
 
   // Toggle settings
   $toggles = array(
@@ -432,7 +436,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
   );
   foreach ($toggles as $name => $title) {
     if ((!$key) || in_array($name, $features)) {
-      $form['theme_settings']['toggle_' . $name] = array('#type' => 'checkbox', '#title' => $title, '#default_value' => theme_get_setting('toggle_' . $name, $key));
+      $form['theme_settings']['toggle_' . $name] = array('#type' => 'checkbox', '#title' => $title, '#default_value' => theme_get_setting('features.' . $name, $key));
       // Disable checkboxes for features not supported in the current configuration.
       if (isset($disabled['toggle_' . $name])) {
         $form['theme_settings']['toggle_' . $name]['#disabled'] = TRUE;
@@ -456,7 +460,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
     $form['logo']['default_logo'] = array(
       '#type' => 'checkbox',
       '#title' => t('Use the default logo supplied by the theme'),
-      '#default_value' => theme_get_setting('default_logo', $key),
+      '#default_value' => theme_get_setting('logo.use_default', $key),
       '#tree' => FALSE,
     );
     $form['logo']['settings'] = array(
@@ -471,7 +475,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
     $form['logo']['settings']['logo_path'] = array(
       '#type' => 'textfield',
       '#title' => t('Path to custom logo'),
-      '#default_value' => theme_get_setting('logo_path', $key),
+      '#default_value' => theme_get_setting('logo.path', $key),
     );
     $form['logo']['settings']['logo_upload'] = array(
       '#type' => 'file',
@@ -490,7 +494,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
     $form['favicon']['default_favicon'] = array(
       '#type' => 'checkbox',
       '#title' => t('Use the default shortcut icon supplied by the theme'),
-      '#default_value' => theme_get_setting('default_favicon', $key),
+      '#default_value' => theme_get_setting('favicon.use_default', $key),
     );
     $form['favicon']['settings'] = array(
       '#type' => 'container',
@@ -504,7 +508,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
     $form['favicon']['settings']['favicon_path'] = array(
       '#type' => 'textfield',
       '#title' => t('Path to custom icon'),
-      '#default_value' => theme_get_setting('favicon_path', $key),
+      '#default_value' => theme_get_setting('favicon.path', $key),
     );
     $form['favicon']['settings']['favicon_upload'] = array(
       '#type' => 'file',
@@ -598,12 +602,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
     }
   }
 
-  $form = system_settings_form($form);
-  // We don't want to call system_settings_form_submit(), so change #submit.
-  array_pop($form['#submit']);
-  $form['#submit'][] = 'system_theme_settings_submit';
-  $form['#validate'][] = 'system_theme_settings_validate';
-  return $form;
+  return system_config_form($form, $form_state);
 }
 
 /**
@@ -698,14 +697,15 @@ function _system_theme_settings_validate_path($path) {
  * Process system_theme_settings form submissions.
  */
 function system_theme_settings_submit($form, &$form_state) {
+  $config = config($form_state['values']['config_key']);
+
   // Exclude unnecessary elements before saving.
   form_state_values_clean($form_state);
-  $values = $form_state['values'];
+  $key = $form_state['values']['var'];
+  unset($form_state['values']['var']);
+  unset($form_state['values']['config_key']);
 
-  // Extract the name of the theme from the submitted form values, then
-  // remove it from the array so that it is not saved as part of the variable.
-  $key = $values['var'];
-  unset($values['var']);
+  $values = $form_state['values'];
 
   // If the user uploaded a new logo or favicon, save it to a permanent location
   // and use it in place of the default theme-provided file.
@@ -739,8 +739,7 @@ function system_theme_settings_submit($form, &$form_state) {
     }
   }
 
-  variable_set($key, $values);
-  drupal_set_message(t('The configuration options have been saved.'));
+  theme_settings_convert_to_config($values, $config)->save();
 
   cache_invalidate_tags(array('content' => TRUE));
 }
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index cfc9a4e..1d09794 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -2095,6 +2095,30 @@ function system_update_8048() {
 }
 
 /**
+ * Move system theme settings from variables to config.
+ */
+function system_update_8049() {
+  // Build a list of themes to convert and install default config if provided.
+  $theme_settings_to_config_map = array('theme_settings' => 'system.theme.global');
+  update_7_to_8_install_default_config('module', 'system.theme.global');
+  $themes = list_themes();
+  foreach ($themes as $theme) {
+    $theme_settings_to_config_map['theme_' . $theme->name . '_settings'] = $theme->name . '.settings';
+    update_7_to_8_install_default_config('theme', $theme->name . '.settings');
+  }
+
+  // Converts array of theme settings from Drupal 7's variable system to Drupal
+  // 8's configuration management system.
+  foreach ($theme_settings_to_config_map as $variable => $config_name) {
+    $config = config($config_name);
+    $theme_settings = update_variable_get($variable);
+    if (!empty($theme_settings)) {
+      theme_settings_convert_to_config($theme_settings, $config)->save();
+    }
+  }
+}
+
+/**
  * @} End of "defgroup updates-7.x-to-8.x".
  * The next series of updates should start at 9000.
  */
diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php
index 0001cba..60584b8 100644
--- a/core/modules/system/theme.api.php
+++ b/core/modules/system/theme.api.php
@@ -87,7 +87,7 @@ function hook_form_system_theme_settings_alter(&$form, &$form_state) {
   $form['toggle_breadcrumb'] = array(
     '#type' => 'checkbox',
     '#title' => t('Display the breadcrumb'),
-    '#default_value' => theme_get_setting('toggle_breadcrumb'),
+    '#default_value' => theme_get_setting('features.breadcrumb'),
     '#description'   => t('Show a trail of links from the homepage to the current page.'),
   );
 }
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserPictureTest.php b/core/modules/user/lib/Drupal/user/Tests/UserPictureTest.php
index 7764699..4c7ea56 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserPictureTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserPictureTest.php
@@ -97,20 +97,32 @@ function testPictureOnNodeComment() {
     $node = $this->drupalCreateNode(array('type' => 'article'));
 
     // Enable user pictures on nodes.
-    variable_set('theme_settings', array('toggle_node_user_picture' => TRUE));
+    config('system.theme.global')->set('features.node_user_picture', TRUE)->save();
 
     // Verify that the image is displayed on the user account page.
     $this->drupalGet('node/' . $node->nid);
     $this->assertRaw(file_uri_target($file->uri), 'User picture found on node page.');
 
     // Enable user pictures on comments, instead of nodes.
-    variable_set('theme_settings', array('toggle_comment_user_picture' => TRUE));
+    config('system.theme.global')
+      ->set('features.node_user_picture', FALSE)
+      ->set('features.comment_user_picture', TRUE)
+      ->save();
 
     $edit = array(
       'comment_body[' . LANGUAGE_NOT_SPECIFIED . '][0][value]' => $this->randomString(),
     );
     $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Save'));
     $this->assertRaw(file_uri_target($file->uri), 'User picture found on comment.');
+
+    // Disable user pictures on comments and nodes.
+    config('system.theme.global')
+      ->set('features.node_user_picture', FALSE)
+      ->set('features.comment_user_picture', FALSE)
+      ->save();
+
+    $this->drupalGet('node/' . $node->nid);
+    $this->assertNoRaw(file_uri_target($file->uri), 'User picture not found on node and comment.');
   }
 
   /**
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 19dc974..b6f2a34 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -732,7 +732,7 @@ function template_preprocess_username(&$variables) {
   $variables['extra'] = '';
   if (empty($account->uid)) {
    $variables['uid'] = 0;
-   if (theme_get_setting('toggle_comment_user_verification')) {
+   if (theme_get_setting('features.comment_user_verification')) {
      $variables['extra'] = ' (' . t('not verified') . ')';
    }
   }
diff --git a/core/themes/bartik/bartik.info b/core/themes/bartik/bartik.info
index c0c206d..b89a2a5 100644
--- a/core/themes/bartik/bartik.info
+++ b/core/themes/bartik/bartik.info
@@ -30,4 +30,5 @@ regions[footer_thirdcolumn] = Footer third column
 regions[footer_fourthcolumn] = Footer fourth column
 regions[footer] = Footer
 
+; @todo D8: Remove once themes have to be installed.
 settings[shortcut_module_link] = 0
diff --git a/core/themes/bartik/color/color.inc b/core/themes/bartik/color/color.inc
index 50ce731..f70450c 100644
--- a/core/themes/bartik/color/color.inc
+++ b/core/themes/bartik/color/color.inc
@@ -6,7 +6,7 @@
  */
 
 // Put the logo path into JavaScript for the live preview.
-drupal_add_js(array('color' => array('logo' => theme_get_setting('logo', 'bartik'))), 'setting');
+drupal_add_js(array('color' => array('logo' => theme_get_setting('logo.url', 'bartik'))), 'setting');
 
 $info = array(
   // Available colors and color labels used in theme.
diff --git a/core/themes/bartik/config/bartik.settings.yml b/core/themes/bartik/config/bartik.settings.yml
new file mode 100644
index 0000000..67537ae
--- /dev/null
+++ b/core/themes/bartik/config/bartik.settings.yml
@@ -0,0 +1 @@
+shortcut_module_link: '0'
diff --git a/core/themes/bartik/template.php b/core/themes/bartik/template.php
index 9a6c8a9..8b730f2 100644
--- a/core/themes/bartik/template.php
+++ b/core/themes/bartik/template.php
@@ -50,8 +50,8 @@ function bartik_process_page(&$variables) {
   }
   // Always print the site name and slogan, but if they are toggled off, we'll
   // just hide them visually.
-  $variables['hide_site_name']   = theme_get_setting('toggle_name') ? FALSE : TRUE;
-  $variables['hide_site_slogan'] = theme_get_setting('toggle_slogan') ? FALSE : TRUE;
+  $variables['hide_site_name']   = theme_get_setting('features.name') ? FALSE : TRUE;
+  $variables['hide_site_slogan'] = theme_get_setting('features.slogan') ? FALSE : TRUE;
   if ($variables['hide_site_name']) {
     // If toggle_name is FALSE, the site_name will be empty, so we rebuild it.
     $variables['site_name'] = check_plain($site_config->get('name'));
@@ -98,8 +98,8 @@ function bartik_process_maintenance_page(&$variables) {
   $site_config = config('system.site');
   // Always print the site name and slogan, but if they are toggled off, we'll
   // just hide them visually.
-  $variables['hide_site_name']   = theme_get_setting('toggle_name') ? FALSE : TRUE;
-  $variables['hide_site_slogan'] = theme_get_setting('toggle_slogan') ? FALSE : TRUE;
+  $variables['hide_site_name']   = theme_get_setting('features.name') ? FALSE : TRUE;
+  $variables['hide_site_slogan'] = theme_get_setting('features.slogan') ? FALSE : TRUE;
   if ($variables['hide_site_name']) {
     // If toggle_name is FALSE, the site_name will be empty, so we rebuild it.
     $variables['site_name'] = check_plain($site_config->get('name'));
diff --git a/core/themes/seven/config/seven.settings.yml b/core/themes/seven/config/seven.settings.yml
new file mode 100644
index 0000000..7955d25
--- /dev/null
+++ b/core/themes/seven/config/seven.settings.yml
@@ -0,0 +1 @@
+shortcut_module_link: '1'
diff --git a/core/themes/seven/seven.info b/core/themes/seven/seven.info
index b737eaf..a646e66 100644
--- a/core/themes/seven/seven.info
+++ b/core/themes/seven/seven.info
@@ -9,11 +9,12 @@ stylesheets-override[] = vertical-tabs.css
 stylesheets-override[] = vertical-tabs-rtl.css
 stylesheets-override[] = jquery.ui.theme.css
 
-settings[shortcut_module_link] = 1
-
 regions[content] = Content
 regions[help] = Help
 regions[page_top] = Page top
 regions[page_bottom] = Page bottom
 regions[sidebar_first] = First sidebar
 regions_hidden[] = sidebar_first
+
+; @todo D8: Remove once themes have to be installed.
+settings[shortcut_module_link] = 1
diff --git a/core/themes/stark/config/stark.settings.yml b/core/themes/stark/config/stark.settings.yml
new file mode 100644
index 0000000..67537ae
--- /dev/null
+++ b/core/themes/stark/config/stark.settings.yml
@@ -0,0 +1 @@
+shortcut_module_link: '0'
