diff --git a/core/includes/config.inc b/core/includes/config.inc
index 3ffcaec..afcaf49 100644
--- a/core/includes/config.inc
+++ b/core/includes/config.inc
@@ -1,6 +1,7 @@
 <?php
 
 use Drupal\Core\Config\Config;
+use Drupal\Core\Config\ConfigMetadata;
 use Drupal\Core\Config\FileStorage;
 use Drupal\Core\Config\NullStorage;
 use Drupal\Core\Config\StorageInterface;
@@ -104,6 +105,23 @@ function config_sync_get_changes(StorageInterface $source_storage, StorageInterf
 }
 
 /**
+ * Retrieves a metadata object for a configuration object or key.
+ *
+ * @param $name
+ *   The name of the configuration object for which we want to build a metadata object.
+ *
+ * @return Drupal\Core\Config\ConfigMetadata
+ *   An metadata object that contains the full metadata for the reguested name.
+ */
+function config_metadata($name) {
+  $meta = &drupal_static(__FUNCTION__);
+  if (!isset($meta[$name])) {
+    $meta[$name] = new ConfigMetadata($name);
+  }
+  return $meta[$name];
+}
+
+/**
  * Writes an array of config file changes from a source storage to a target storage.
  *
  * @param array $config_changes
diff --git a/core/lib/Drupal/Core/Config/ConfigMetadata.php b/core/lib/Drupal/Core/Config/ConfigMetadata.php
new file mode 100644
index 0000000..30cad01
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigMetadata.php
@@ -0,0 +1,415 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Config\ConfigMetadata.
+ *
+ * Metadata lives in a modules 'meta' directory, next to the 'config' directory,
+ * which contains the actual configuration. For each entry in an actual
+ * configuration file, the corresponding metadata file contains an entry with
+ * the following sub-keys:
+ * - label: The human-readable name for this configuration item.
+ * - type: The data type of this configuration item. Valid types include string,
+ *   boolean, integer, and other types defined by hook_data_type_info() ...
+ *
+ * The name of the configuration object may contain the placeholder '__' as the
+ * last component, which denotes generic metadata for all objects of this
+ * type. For the 'large' image style, for example, both "image.style.__" and
+ * "image.style.large" would be valid metadata files. In case both of these
+ * files exist, we load the generic metadata (in this example from
+ * "image.style.__") first and add the specific metadata (in this example from
+ * "image.style.large") on top of it.
+ */
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\Config;
+use Drupal\Core\Config\FileStorage;
+use Drupal\Component\Utility\NestedArray;
+use Symfony\Component\Yaml\Parser;
+
+/**
+ * Defines the default configuration metadata object.
+ */
+class ConfigMetadata {
+
+  /**
+   * Filesystem marker for base metadata name.
+   */
+  const BASE_MARK = '__';
+
+  /**
+   * The name of the configuration object.
+   *
+   * @var string
+   */
+  protected $name;
+
+  /**
+   * The medatada of the configuration object.
+   *
+   * @var array
+   */
+  protected $metadata;
+
+  /**
+   * The built data of the configuration object.
+   *
+   * @var array
+   */
+  protected $data;
+
+  /**
+   * Constructs a configuration metadata object.
+   *
+   * @param string $name
+   *   The name of the configuration object being constructed.
+   */
+  public function __construct($name) {
+    $this->name = $name;
+  }
+
+  /**
+   * Gets built data + metadata array from this config metadata.
+   *
+   * An array of built data contains the 'label' and 'type' keys as explained above.
+   * If $key is omitted, a nested array is returned, where the array keys are the
+   * metadata keys and the values are the metadata arrays (see above).
+   *
+   * @param $key
+   *   Optional string that maps to a key within the configuration metadata.
+   * @return
+   *   The built data property that was requested or the full data array.
+   */
+  public function get($key = '') {
+    if (!isset($this->data)) {
+      $this->build();
+    }
+    if ($key) {
+      return issset($this->data[$key]) ? $this->data[$key] : NULL;
+    }
+    else {
+      return isset($this->data) ? $this->data : array();
+    }
+  }
+
+  /**
+   * Gets medata array from this config metadata.
+   *
+   * An array of metadata contains the 'label' and 'type' keys as explained above.
+   * If $key is omitted, a nested array is returned, where the array keys are the
+   * metadata keys and the values are the metadata arrays (see above).
+   *
+   * @param $key
+   *   Optional string that maps to a key within the configuration metadata.
+   * @return
+   *   The metadata property that was requested or the full metadata array.
+   */
+  public function getMetadata($key = '') {
+    if (!isset($this->metadata)) {
+      $this->load();
+    }
+    if ($key) {
+      return issset($this->metadata[$key]) ? $this->metadata[$key] : NULL;
+    }
+    else {
+      return $this->metadata;
+    }
+  }
+
+  /**
+   * Load metadata.
+   */
+  public function load() {
+    // Get base metadata if available.
+    if ($basename = $this->getBaseName($this->name)) {
+      $this->metadata = $this->read($basename);
+    }
+    // Merge current metadata on top of it.
+    if ($meta = $this->read($this->name)) {
+      $this->metadata = NestedArray::mergeDeep($this->metadata, $meta);
+    }
+    return $this;
+  }
+
+  /**
+   * Matches metadata against real configuration data.
+   *
+   * The result will be an array merging the full configuration data and
+   * the metadata. The array keys will be the property names with prefixes
+   * and the array values will be arrays that have the following keys:
+   * - 'type', Data type
+   * - 'value', Value of this property for the configuration object.
+   *
+   * Example:
+   *
+   * - Data: module/system/config/system.site.yml
+   *
+   *   name: Drupal
+   *     mail: ''
+   *     slogan: ''
+   *   page:
+   *     403: ''
+   *     404: ''
+   *     front: user
+   *
+   * - Metadata: module/system/meta/system.site.yml
+   *
+   *   name:
+   *     label: 'Site name'
+   *     type: 'string'
+   *   mail:
+   *     label: 'Site mail'
+   *     type: 'email'
+   *   slogan:
+   *     label: 'Site slogan'
+   *     type: 'string'
+   *   page:
+   *     label: 'Error pages'
+   *     type: config_subkeys
+   *   page.403:
+   *     label: 'Default 403 (access denied) page'
+   *     type: 'path'
+   *   page.404:
+   *     label: 'Default 404 (not found) page'
+   *     type: 'path'
+   *   page.front:
+   *     label: 'Default front page'
+   *     type: 'path'
+   *
+   * - Built array (data + metadata)
+   *
+   *   name:
+   *     label: 'Site name'
+   *     type: 'string'
+   *     value: 'Drupal'
+   *   mail:
+   *     label: 'Site mail'
+   *     type: 'email'
+   *     value: ''
+   *   slogan:
+   *     label: 'Site slogan'
+   *     type: 'string'
+   *     value: ''
+   *   page:
+   *     label: 'Error pages'
+   *     type: config_subkeys
+   *   page.403:
+   *     label: 'Default 403 (access denied) page'
+   *     type: 'path'
+   *     value ''
+   *   page.404:
+   *     label: 'Default 404 (not found) page'
+   *     type: 'path'
+   *     value: ''
+   *   page.front:
+   *     label: 'Default front page'
+   *     type: 'path'
+   *     value 'node'
+   *
+   * @param $data
+   *   Optional array of configuration data to be built.
+   *   If not present use current configuration data.
+   * @return array
+   *   Configuration data merged with metadata.
+   */
+  public function build($data = NULL) {
+    $data = isset($data) ? $data : config($this->name)->get();
+    $this->data = $this->buildData($data, $this->getMetadata());
+    return $this;
+  }
+
+  /**
+   * Build multiple configuration elements.
+   *
+   * @param $data
+   *   Array of configuration data.
+   * @param $meta
+   *   Array of configuration metadata.
+   */
+  protected static function buildData($data, $meta) {
+    $build = array();
+    foreach ($data as $key => $value) {
+      if (isset($meta[$key])) {
+        $build += self::buildElement($value, $meta[$key], $key);
+      }
+      else {
+        // No metadata for this key, add plain value.
+        $build[$key] = array(
+          'type' => 'value',
+          'value' => $value,
+        );
+      }
+    }
+    return $build;
+  }
+
+  /**
+   * Build configuration element with data and metadata.
+   *
+   * @param $key
+   *   Element key
+   * @param $base
+   *   Base name for this element.
+   * @param $index
+   *   Index of this element in the data array.
+   *
+   * @result array
+   *   Built metadata array with one or more elements.
+   */
+  protected static function buildElement($data, $meta, $key) {
+    if (!isset($meta['type'])) {
+      $meta['type'] = 'value';
+    }
+    $build[$key] = $meta;
+    // Build element depending on type.
+    switch ($meta['type']) {
+      case 'config_nested':
+        // This is an array of nested configuration elements.
+        $nested = self::buildNested($data, $meta);
+        $build += self::addPrefix($key, $nested);
+        break;
+      case 'config_subkeys':
+        // Array with multiple nested properties.
+        $build += self::buildSubkeys($data, $meta, $key);
+        break;
+      default:
+        // Just return metadata, adding the data in 'value'.
+        $build[$key]['value'] = $data;
+    }
+    return $build;
+  }
+
+  /**
+   * Build nested configuration array.
+   *
+   * Example metadata from image.style.+.yml
+   *
+   * effects:
+   *   label: 'Style effects'
+   *   type: 'nested_config'
+   *   config_name: 'image.style.effects.*'
+   *
+   * Example data from image.style.large.yml
+   *
+   * effects:
+   *   ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d:
+   *     name: image.style.effects.scale
+   *     data:
+   *       width: '480'
+   *       height: '480'
+   *       upscale: '1'
+   *     weight: '0'
+   *     ieid: ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d
+   */
+ protected static function buildNested($data, $meta) {
+   $build = array();
+   foreach ($data as $key => $value) {
+     // For nested elements, the parent metadata file declares the child element
+     // using the 'config_name' key. Actual configuration files directly specify
+     // the nested configuration in one file and denote the child element with
+     // the 'name' key.
+     $name = isset($value['name']) ? $value['name'] : $meta['config_name'];
+     $build = self::addPrefix($key, config_metadata($name)->build($value)->get());
+   }
+   return $build;
+ }
+
+  /**
+   * Build array of configuration data with subkeys.
+   *
+   * Example metadata from image.style.effects.+.yml + image.style.effects.scale.yml
+   *
+   * data:
+   *   label: 'Data'
+   *   type: 'config_subkeys'
+   * data.width:
+   *   label: 'Width'
+   *   type: 'integer'
+   * data.height:
+   *   label: 'Height'
+   *   type: 'integer'
+   * data.upscale:
+   *  label: 'Upscale'
+   *  type: 'boolean'
+   *
+   * Example data from image.style.large.yml (effects/../data)
+   *
+   *    width: '480'
+   *    height: '480'
+   *    upscale: '1'
+   *
+   * @param $data
+   *   Array of configuration data.
+   * @param $meta
+   *
+   * @param $key
+   *   Key to prepend to the data to match it with the metadata.
+   */
+  protected static function buildSubkeys($data, $meta, $key) {
+    // Prefix all data with given key and build as usual.
+    $data = self::addPrefix($key, $data);
+    return self::buildData($data, $meta);
+  }
+
+  /**
+   * Add prefix to array keys.
+   *
+   * @param $prefix
+   *   Configuration name to prepend to all of the array keys.
+   * @param $data
+   *   Array with keys to be prefixed.
+   *
+   * @return array
+   *   Data array with the prefixed keys and the same values.
+   */
+  protected static function addPrefix($prefix, $data) {
+    $result = array();
+    foreach ($data as $key => $value) {
+      $result[$prefix . '.' . $key] = $value;
+    }
+    return $result;
+  }
+
+  /**
+   * Get parent metadata name.
+   */
+  protected static function getBaseName($name) {
+    $parts = explode('.', $name);
+    $last = array_pop($parts);
+    // If this is not the generic metadata (where the last component of the
+    // name is a '+'), try to load that first.
+    if ($last != self::BASE_MARK) {
+      return implode('.', array_merge($parts, array(self::BASE_MARK)));
+    }
+  }
+
+  /**
+   * Read metadata from file system.
+   *
+   * @return array
+   *   Metadata array if found or empty array if not.
+   */
+  protected static function read($name) {
+    $module = strtok($name, '.');
+    // We are looking for a file in $module/meta/$name.yml
+    $directory = drupal_get_path('module', $module) . '/meta';
+    $filepath = $directory  . '/' . $name . '.yml';
+    if (file_exists($filepath)) {
+      // We use FileStorage as a convenience though we could add our
+      // own reader and parser here.
+      try {
+        $storage = new FileStorage($directory);
+        return $storage->read($name);
+      }
+      catch (Drupal\Core\Config\FileStorageReadException $e) {
+        // Either the file does not exist or we cannot decode it.
+        // Do nothing. In the worst case, the value will be an empty array.
+        // @todo In that worst case, we should probably at least watchdog() or
+        //   something.
+      }
+    }
+    return array();
+  }
+
+}
\ No newline at end of file
diff --git a/core/modules/image/config/image.style.large.yml b/core/modules/image/config/image.style.large.yml
index 3a1260d..05896b1 100644
--- a/core/modules/image/config/image.style.large.yml
+++ b/core/modules/image/config/image.style.large.yml
@@ -1,10 +1,11 @@
 name: large
 effects:
   ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d:
-    name: image_scale
+    name: image.style.effects.scale
     data:
       width: '480'
       height: '480'
       upscale: '1'
     weight: '0'
     ieid: ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d
+
diff --git a/core/modules/image/config/image.style.medium.yml b/core/modules/image/config/image.style.medium.yml
index 3f2b445..44e882a 100644
--- a/core/modules/image/config/image.style.medium.yml
+++ b/core/modules/image/config/image.style.medium.yml
@@ -1,7 +1,7 @@
 name: medium
 effects:
   bddf0d06-42f9-4c75-a700-a33cafa25ea0:
-    name: image_scale
+    name: image.style.effects.scale
     data:
       width: '220'
       height: '220'
diff --git a/core/modules/image/config/image.style.thumbnail.yml b/core/modules/image/config/image.style.thumbnail.yml
index 83e6730..de61ab5 100644
--- a/core/modules/image/config/image.style.thumbnail.yml
+++ b/core/modules/image/config/image.style.thumbnail.yml
@@ -1,7 +1,7 @@
 name: thumbnail
 effects:
   1cfec298-8620-4749-b100-ccb6c4500779:
-    name: image_scale
+    name: image.style.effects.scale
     data:
       width: '100'
       height: '100'
diff --git a/core/modules/image/image.api.php b/core/modules/image/image.api.php
index 758d38b..1fc523a 100644
--- a/core/modules/image/image.api.php
+++ b/core/modules/image/image.api.php
@@ -179,12 +179,12 @@ function hook_image_default_styles() {
   $styles['mymodule_preview'] = array(
     'effects' => array(
       array(
-        'name' => 'image_scale',
+        'name' => 'image.style.effects.scale',
         'data' => array('width' => 400, 'height' => 400, 'upscale' => 1),
         'weight' => 0,
       ),
       array(
-        'name' => 'image_desaturate',
+        'name' => 'image.style.effects.desaturate',
         'data' => array(),
         'weight' => 1,
       ),
diff --git a/core/modules/image/image.effects.inc b/core/modules/image/image.effects.inc
index 35a6a74..d491796 100644
--- a/core/modules/image/image.effects.inc
+++ b/core/modules/image/image.effects.inc
@@ -10,7 +10,7 @@
  */
 function image_image_effect_info() {
   $effects = array(
-    'image_resize' => array(
+    'image.style.effects.resize' => array(
       'label' => t('Resize'),
       'help' => t('Resizing will make images an exact set of dimensions. This may cause images to be stretched or shrunk disproportionately.'),
       'effect callback' => 'image_resize_effect',
@@ -18,7 +18,7 @@ function image_image_effect_info() {
       'form callback' => 'image_resize_form',
       'summary theme' => 'image_resize_summary',
     ),
-    'image_scale' => array(
+    'image.style.effects.scale' => array(
       'label' => t('Scale'),
       'help' => t('Scaling will maintain the aspect-ratio of the original image. If only a single dimension is specified, the other dimension will be calculated.'),
       'effect callback' => 'image_scale_effect',
@@ -26,7 +26,7 @@ function image_image_effect_info() {
       'form callback' => 'image_scale_form',
       'summary theme' => 'image_scale_summary',
     ),
-    'image_scale_and_crop' => array(
+    'image.style.effects.scale_and_crop' => array(
       'label' => t('Scale and crop'),
       'help' => t('Scale and crop will maintain the aspect-ratio of the original image, then crop the larger dimension. This is most useful for creating perfectly square thumbnails without stretching the image.'),
       'effect callback' => 'image_scale_and_crop_effect',
@@ -34,7 +34,7 @@ function image_image_effect_info() {
       'form callback' => 'image_resize_form',
       'summary theme' => 'image_resize_summary',
     ),
-    'image_crop' => array(
+    'image.style.effects.crop' => array(
       'label' => t('Crop'),
       'help' => t('Cropping will remove portions of an image to make it the specified dimensions.'),
       'effect callback' => 'image_crop_effect',
@@ -42,13 +42,13 @@ function image_image_effect_info() {
       'form callback' => 'image_crop_form',
       'summary theme' => 'image_crop_summary',
     ),
-    'image_desaturate' => array(
+    'image.style.effects.desaturate' => array(
       'label' => t('Desaturate'),
       'help' => t('Desaturate converts an image to grayscale.'),
       'effect callback' => 'image_desaturate_effect',
       'dimensions passthrough' => TRUE,
     ),
-    'image_rotate' => array(
+    'image.style.effects.rotate' => array(
       'label' => t('Rotate'),
       'help' => t('Rotating an image may cause the dimensions of an image to increase to fit the diagonal.'),
       'effect callback' => 'image_rotate_effect',
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
index f2f8b0b..860cf33 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
@@ -67,28 +67,28 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
     $style_name = strtolower($this->randomName(10));
     $style_path = 'admin/config/media/image-styles/edit/' . $style_name;
     $effect_edits = array(
-      'image_resize' => array(
+      'image.style.effects.resize' => array(
         'data[width]' => 100,
         'data[height]' => 101,
       ),
-      'image_scale' => array(
+      'image.style.effects.scale' => array(
         'data[width]' => 110,
         'data[height]' => 111,
         'data[upscale]' => 1,
       ),
-      'image_scale_and_crop' => array(
+      'image.style.effects.scale_and_crop' => array(
         'data[width]' => 120,
         'data[height]' => 121,
       ),
-      'image_crop' => array(
+      'image.style.effects.crop' => array(
         'data[width]' => 130,
         'data[height]' => 131,
         'data[anchor]' => 'center-center',
       ),
-      'image_desaturate' => array(
+      'image.style.effects.desaturate' => array(
         // No options for desaturate.
       ),
-      'image_rotate' => array(
+      'image.style.effects.rotate' => array(
         'data[degrees]' => 5,
         'data[random]' => 1,
         'data[bgcolor]' => '#FFFF00',
@@ -266,7 +266,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
     // Add a scale effect.
     $this->drupalGet('admin/config/media/image-styles/add');
     $this->drupalPost(NULL, array('name' => 'test_style_effect_edit'), t('Create new style'));
-    $this->drupalPost(NULL, array('new' => 'image_scale_and_crop'), t('Add'));
+    $this->drupalPost(NULL, array('new' => 'image.style.effects.scale_and_crop'), t('Add'));
     $this->drupalPost(NULL, array('data[width]' => '300', 'data[height]' => '200'), t('Add effect'));
     $this->assertText(t('Scale and crop 300x200'));
 
@@ -281,13 +281,13 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
     // Add another scale effect.
     $this->drupalGet('admin/config/media/image-styles/add');
     $this->drupalPost(NULL, array('name' => 'test_style_scale_edit_scale'), t('Create new style'));
-    $this->drupalPost(NULL, array('new' => 'image_scale'), t('Add'));
+    $this->drupalPost(NULL, array('new' => 'image.style.effects.scale'), t('Add'));
     $this->drupalPost(NULL, array('data[width]' => '12', 'data[height]' => '19'), t('Add effect'));
 
     // Edit the scale effect that was just added.
     $this->clickLink(t('edit'));
     $this->drupalPost(NULL, array('data[width]' => '24', 'data[height]' => '19'), t('Update effect'));
-    $this->drupalPost(NULL, array('new' => 'image_scale'), t('Add'));
+    $this->drupalPost(NULL, array('new' => 'image.style.effects.scale'), t('Add'));
 
     // Add another scale effect and make sure both exist.
     $this->drupalPost(NULL, array('data[width]' => '12', 'data[height]' => '19'), t('Add effect'));
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
index d2554cf..c3d141f 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
@@ -58,7 +58,7 @@ class ImageDimensionsTest extends WebTestBase {
 
     // Scale an image that is wider than it is high.
     $effect = array(
-      'name' => 'image_scale',
+      'name' => 'image.style.effects.scale',
       'data' => array(
         'width' => 120,
         'height' => 90,
@@ -80,7 +80,7 @@ class ImageDimensionsTest extends WebTestBase {
 
     // Rotate 90 degrees anticlockwise.
     $effect = array(
-      'name' => 'image_rotate',
+      'name' => 'image.style.effects.rotate',
       'data' => array(
         'degrees' => -90,
         'random' => FALSE,
@@ -101,7 +101,7 @@ class ImageDimensionsTest extends WebTestBase {
 
     // Scale an image that is higher than it is wide (rotated by previous effect).
     $effect = array(
-      'name' => 'image_scale',
+      'name' => 'image.style.effects.scale',
       'data' => array(
         'width' => 120,
         'height' => 90,
@@ -123,7 +123,7 @@ class ImageDimensionsTest extends WebTestBase {
 
     // Test upscale disabled.
     $effect = array(
-      'name' => 'image_scale',
+      'name' => 'image.style.effects.scale',
       'data' => array(
         'width' => 400,
         'height' => 200,
@@ -145,7 +145,7 @@ class ImageDimensionsTest extends WebTestBase {
 
     // Add a desaturate effect.
     $effect = array(
-      'name' => 'image_desaturate',
+      'name' => 'image.style.effects.desaturate',
       'data' => array(),
       'weight' => 4,
     );
@@ -163,7 +163,7 @@ class ImageDimensionsTest extends WebTestBase {
 
     // Add a random rotate effect.
     $effect = array(
-      'name' => 'image_rotate',
+      'name' => 'image.style.effects.rotate',
       'data' => array(
         'degrees' => 180,
         'random' => TRUE,
@@ -182,7 +182,7 @@ class ImageDimensionsTest extends WebTestBase {
 
     // Add a crop effect.
     $effect = array(
-      'name' => 'image_crop',
+      'name' => 'image.style.effects.crop',
       'data' => array(
         'width' => 30,
         'height' => 30,
@@ -204,7 +204,7 @@ class ImageDimensionsTest extends WebTestBase {
 
     // Rotate to a non-multiple of 90 degrees.
     $effect = array(
-      'name' => 'image_rotate',
+      'name' => 'image.style.effects.rotate',
       'data' => array(
         'degrees' => 57,
         'random' => FALSE,
diff --git a/core/modules/image/meta/image.style.__.yml b/core/modules/image/meta/image.style.__.yml
new file mode 100644
index 0000000..736effc
--- /dev/null
+++ b/core/modules/image/meta/image.style.__.yml
@@ -0,0 +1,7 @@
+name:
+  label: 'Machine name'
+  type: 'machine_name'
+effects:
+  label: 'Style effects'
+  type: 'config_nested'
+  config_name: 'image.style.effects.*'
diff --git a/core/modules/image/meta/image.style.effects.__.yml b/core/modules/image/meta/image.style.effects.__.yml
new file mode 100644
index 0000000..08bbaf5
--- /dev/null
+++ b/core/modules/image/meta/image.style.effects.__.yml
@@ -0,0 +1,11 @@
+name:
+  label: 'Style name'
+data:
+  label: 'Data'
+  type: 'config_subkeys'
+weight:
+  label: 'Weight'
+  type: 'weight'
+ieid:
+  label: 'IEID'
+  type: 'ieid'
diff --git a/core/modules/image/meta/image.style.effects.scale.yml b/core/modules/image/meta/image.style.effects.scale.yml
new file mode 100644
index 0000000..ad140c1
--- /dev/null
+++ b/core/modules/image/meta/image.style.effects.scale.yml
@@ -0,0 +1,9 @@
+data.width:
+  label: 'Width'
+  type: 'integer'
+data.height:
+  label: 'Height'
+  type: 'integer'
+data.upscale:
+  label: 'Upscale'
+  type: 'boolean'
diff --git a/core/modules/system/meta/system.maintenance.yml b/core/modules/system/meta/system.maintenance.yml
new file mode 100644
index 0000000..0f4cd6d
--- /dev/null
+++ b/core/modules/system/meta/system.maintenance.yml
@@ -0,0 +1,6 @@
+enabled:
+  label: 'Put site into maintenance mode'
+  type: 'boolean'
+message:
+  label: 'Message to display when in maintenance mode'
+  type: 'string'
diff --git a/core/modules/system/meta/system.site.yml b/core/modules/system/meta/system.site.yml
new file mode 100644
index 0000000..f09e316
--- /dev/null
+++ b/core/modules/system/meta/system.site.yml
@@ -0,0 +1,21 @@
+name:
+  label: 'Site name'
+  type: 'string'
+mail:
+  label: 'Site mail'
+  type: 'email'
+slogan:
+  label: 'Site slogan'
+  type: 'string'
+page:
+  label: 'Error pages'
+  type: config_subkeys
+page.403:
+    label: 'Default 403 (access denied) page'
+    type: 'path'
+page.404:
+    label: 'Default 404 (not found) page'
+    type: 'path'
+page.front:
+    label: 'Default front page'
+    type: 'path'
\ No newline at end of file
