diff --git skinr.module skinr.module
index 0f62bc0..83382ec 100644
--- skinr.module
+++ skinr.module
@@ -39,6 +39,8 @@ function skinr_init() {
 
 /**
  * Implementation of hook_preprocess().
+ *
+ * @todo Account for drupal's caching being enabled and make it work.
  */
 function skinr_preprocess(&$variables, $hook) {
   // Fix for update script.
@@ -48,27 +50,27 @@ function skinr_preprocess(&$variables, $hook) {
 
   $skinr_config = skinr_fetch_config();
   $current_theme = skinr_current_theme();
-  $theme_registry = theme_get_registry();
 
   $original_hook = $hook;
+  $theme_registry = theme_get_registry();
   if (isset($theme_registry[$hook]['original hook'])) {
     $original_hook = $theme_registry[$hook]['original hook'];
   }
 
-  foreach ($skinr_config as $module => $settings) {
-    if (!empty($settings['preprocess'][$original_hook])) {
-      $preprocess_settings = $settings['preprocess'][$original_hook];
+  foreach ($skinr_config as $module => $module_settings) {
+    if (!empty($module_settings['preprocess'][$original_hook])) {
+      $preprocess_settings = $module_settings['preprocess'][$original_hook];
       $sids = skinr_handler('preprocess_index_handler', 'preprocess', $preprocess_settings['index_handler'], $variables);
 
-      if ($extracted = skinr_skin_extract($module, $sids, $settings, $current_theme)) {
+      if ($extracted = skinr_skin_extract($module, $sids, $current_theme)) {
         foreach ($extracted['css'] as $file) {
           if ($file['enabled']) {
-            _skinr_add_file($file['path'], 'css', $file['media']);
+            drupal_add_css($file['path'], $file['file_options']);
           }
         }
         foreach ($extracted['js'] as $file) {
           if ($file['enabled']) {
-            _skinr_add_file($file['path'], 'js');
+            drupal_add_js($file['path'], $file['file_options']);
           }
         }
         if (!empty($extracted['template'])) {
@@ -88,7 +90,7 @@ function skinr_preprocess(&$variables, $hook) {
   }
 }
 
-function skinr_skin_extract($module, $sids, $settings, $theme = NULL) {
+function skinr_skin_extract($module, $sids, $theme = NULL) {
   if (empty($sids)) {
     return FALSE;
   }
@@ -108,19 +110,16 @@ function skinr_skin_extract($module, $sids, $settings, $theme = NULL) {
     'template' => array(),
   );
 
-  $skins = array();
+  $settings = array();
   foreach ($sids as $sid) {
     if ($skinr = skinr_get($theme, $module, $sid)) {
-      $skins = $skinr->skins + $skins;
+      // @todo Change $skinr->skins to $skinr->settings
+      $settings = $skinr->skins + $settings;
     }
   }
 
-  // Allow other modules to alter the skinr skins array.
-  // @todo Fix this to work with skinr ui.
-  drupal_alter('skinr_skins', $skins, $module, $sids, $settings);
-
-  $extracted['css'] = skinr_skin_get_files($skins, 'css', $theme);
-  $extracted['js'] = skinr_skin_get_files($skins, 'js', $theme);
+  $extracted['css'] = skinr_skin_get_files($settings, 'css', $theme);
+  $extracted['js'] = skinr_skin_get_files($settings, 'js', $theme);
 
   // Add template files.
   if (!empty($skins['_template'])) {
@@ -128,16 +127,16 @@ function skinr_skin_extract($module, $sids, $settings, $theme = NULL) {
     unset($skins['_template']);
   }
 
-  $extracted['classes'] = skinr_flatten_skins_array($skins);
+  $extracted['classes'] = skinr_flatten_skins_array($settings);
 
   return $extracted;
 }
 
 /**
- * Helper function to fetch all css or js files from an array of skins.
+ * Helper function to fetch all css or js files for an array of skins.
  *
- * @param $skins
- *   A an array of available skins.
+ * @param $settings
+ *   A an array of skinr settings.
  * @param $type
  *   Either 'css' or 'js', depending on which files you wish to retrieve from
  *   these skins.
@@ -147,101 +146,79 @@ function skinr_skin_extract($module, $sids, $settings, $theme = NULL) {
  * @return
  *   An array of file data.
  */
-function skinr_skin_get_files($skins, $type, $theme = NULL) {
+function skinr_skin_get_files($settings, $type, $theme = NULL) {
   if (empty($theme)) {
     $theme = skinr_current_theme();
   }
+  if ($type == 'css') {
+    $element = 'stylesheets';
+  }
+  elseif ($type == 'js') {
+    $element = 'scripts';
+  }
+  else {
+    return FALSE;
+  }
 
-  $info = skinr_skin_data();
+  $skins = skinr_skins_load();
   $files = array();
-
-  if ($type == 'css') {
-    foreach ($skins as $skin => $classes) {
-      // Add custom CSS files.
-      if (isset($info[$theme]->skins[$skin])) {
-        if (!empty($info[$theme]->skins[$skin]['stylesheets'])) {
-          foreach ($info[$theme]->skins[$skin]['stylesheets'] as $media => $stylesheets) {
-            foreach ($stylesheets as $file => $path) {
-              $files[] = array(
-                'file' => $file,
-                'path' => $path,
-                'media' => $media,
-                'enabled' => TRUE,
-                'skin' => $skin,
-                'options' => 0,
-              );
-            }
+  foreach ($settings as $skin_name => $classes) {
+    // Check if the $skin_name is enabled for this theme.
+    if (!empty($skins[$skin_name]['status'][$theme])) {
+      // Check if this skin has any stylesheets attached to it.
+      if (!empty($skins[$skin_name][$element])) {
+        foreach ($skins[$skin_name][$element] as $file) {
+          if (is_array($file)) {
+            $data = $file[0];
+            $options = count($file) > 1 ? $file[1] : NULL;
           }
-        }
-        foreach ($info[$theme]->skins[$skin]['options'] as $option_id => $option) {
-          if (!empty($option['stylesheets'])) {
-            foreach ($option['stylesheets'] as $media => $stylesheets) {
-              foreach ($stylesheets as $file => $path) {
-                $enabled = FALSE;
-                if (is_array($classes)) {
-                  if (in_array($option['class'], $classes)) {
-                    $enabled = TRUE;
-                  }
-                }
-                else {
-                  if ($option['class'] == $classes) {
-                    $enabled = TRUE;
-                  }
-                }
-
-                $files[] = array(
-                  'file' => $file,
-                  'path' => $path,
-                  'media' => $media,
-                  'enabled' => $enabled,
-                  'skin' => $skin,
-                  'options' => $option_id,
-                );
-              }
-            }
+          else {
+            $data = $file;
+            $options = NULL;
           }
+          $files[$data] = array(
+            'file' => basename($data),
+            'path' => $data,
+            'file_options' => $options,
+            'enabled' => TRUE,
+            'skin' => $skin_name,
+            'option' => NULL,
+          );
         }
       }
-    }
-  }
-  elseif ($type == 'js') {
-    foreach ($skins as $skin => $classes) {
-      // Add custom JS files.
-      if (isset($info[$theme]->skins[$skin])) {
-        if (isset($info[$theme]->skins[$skin]['scripts'])) {
-          foreach ($info[$theme]->skins[$skin]['scripts'] as $file => $path) {
-            $files[] = array(
-              'file' => $file,
-              'path' => $path,
-              'enabled' => TRUE,
-              'skin' => $skin,
-              'options' => 0,
-            );
-          }
-        }
-        foreach ($info[$theme]->skins[$skin]['options'] as $option_id => $option) {
-          if (isset($option['scripts'])) {
-            foreach ($option['scripts'] as $file => $path) {
-              $enabled = FALSE;
-                if (is_array($classes)) {
-                  if (in_array($option['class'], $classes)) {
-                    $enabled = TRUE;
-                  }
-                }
-                else {
-                  if ($option['class'] == $classes) {
-                    $enabled = TRUE;
-                  }
-                }
-
-              $files[] = array(
-                'file' => $file,
-                'path' => $path,
-                'enabled' => $enabled,
-                'skin' => $skin,
-                'options' => $option_id,
-              );
+
+      foreach ($skins[$skin_name]['options'] as $oid => $option) {
+        if (!empty($option[$element])) {
+          foreach ($option[$element] as $file) {
+            $enabled = FALSE;
+            if (is_array($classes)) {
+              if (in_array($option['class'], $classes)) {
+                $enabled = TRUE;
+              }
+            }
+            elseif ($option['class'] == $classes) {
+              $enabled = TRUE;
+            }
+
+            if (is_array($file)) {
+              $data = $file[0];
+              $options = count($file) > 1 ? $file[1] : NULL;
+            }
+            else {
+              $data = $file;
+              $options = NULL;
             }
+
+            $files[$data] = array(
+              'file' => basename($data),
+              'path' => $data,
+              'file_options' => $options,
+              'skin' => $skin_name,
+              'option' => $oid,
+            );
+            // Allow for other options to set the same file; make sure it's
+            // enabled when required.
+            $files[$data]['enabled'] = (!empty($files[$data]['enabled']) ? $files[$data]['enabled'] : FALSE) || $enabled;
           }
         }
       }
@@ -252,20 +229,6 @@ function skinr_skin_get_files($skins, $type, $theme = NULL) {
 }
 
 /**
- * Helper fuction to add CSS and JS files.
- *
- * The function checks an array of paths for the existence of the file to account for base themes.
- */
-function _skinr_add_file($filename, $type, $media = NULL) {
-  if ($type == 'css') {
-    drupal_add_css($filename, array('weight' => CSS_THEME, 'media' => $media));
-  }
-  else {
-    drupal_add_js($filename, array('weight' => JS_THEME));
-  }
-}
-
-/**
  * Helper function to flatten an array of classes settings.
  */
 function skinr_flatten_skins_array($skins) {
@@ -488,6 +451,8 @@ function skinr_set($skinr) {
  *   A skinr object if both $module and $sid are specified. An array of skinr
  *   objects if only $module is specified. An array of all skinr objects for a
  *   theme if neither $module nor $sid is specified. FALSE on failure.
+ *
+ * @todo Rename $skinr->skins to $skinr->settings throughout the module.
  */
 function skinr_get($theme = NULL, $module = NULL, $sid = NULL) {
   $cache = &drupal_static(__FUNCTION__, array());
@@ -593,21 +558,6 @@ function skinr_current_theme($exclude_admin_theme = FALSE) {
 }
 
 /**
- * Prepare defaults for skins.
- *
- * @return
- *   An array of default skinset settings.
- */
-function skinr_skins_default() {
-  return array(
-    'description' => '',
-    'screenshot' => 'screenshot.png',
-    'php' => DRUPAL_MINIMUM_PHP,
-    'skinr' => array(),
-  );
-}
-
-/**
  * Prepare defaults for skinr options.
  *
  * @return
@@ -624,7 +574,7 @@ function skinr_group_default() {
 }
 
 /**
- * Prepare defaults for skins.
+ * Prepare defaults for a skin.
  *
  * @return
  *   An array of default skins settings.
@@ -641,245 +591,211 @@ function skinr_skin_default() {
     'stylesheets' => array(),
     'scripts' => array(),
     'weight' => NULL,
+    'default_status' => 0,
+    'status' => array(),
   );
 }
 
 /**
- * Helper function to process a skin or theme .info file.
+ * Prepare the default status for a skin.
+ *
+ * @param $default_status
+ *   The default status for all themes for a skin.
  *
  * @return
- *    A skinset.
+ *   An array of default statuses for each enabled theme.
  */
-function _skinr_skinset($info) {
-  $skinset = array(
-    'options' => array('groups' => array()),
-    'skins' => array(),
-  );
-
-  if (!empty($info->info['skinr'])) {
-    $path_root = dirname($info->filename);
-
-    $skinr_info = (array)$info->info['skinr'];
-
-    // Store skinr options.
-    if (!empty($skinr_info['options'])) {
-      $skinset['options'] = $skinr_info['options'];
-      unset($skinr_info['options']);
-
-      if (!isset($skinset['options']['groups'])) {
-        $skinset['options']['groups'] = array();
-      }
-
-      $defaults = skinr_group_default();
-      foreach ($skinset['options']['groups'] as $id => $group) {
-        $skinset['options']['groups'][$id] = array_merge($defaults, $skinset['options']['groups'][$id]);
-        $skinset['options']['groups'][$id]['collapsible'] = (bool)$skinset['options']['groups'][$id]['collapsible'];
-        $skinset['options']['groups'][$id]['collapsed'] = (bool)$skinset['options']['groups'][$id]['collapsed'];
-        $skinset['options']['groups'][$id]['weight'] = $skinset['options']['groups'][$id]['weight'];
-      }
-    }
-
-    $defaults = skinr_skin_default();
-
-    foreach ($skinr_info as $id => $skin) {
-      if (!is_array($skin)) {
-        continue;
-      }
-      $skinset['skins'][$id] = array(
-        'title' => isset($skin['title']) ? $skin['title'] : $defaults['title'],
-        'type' => isset($skin['type']) ? $skin['type'] : $defaults['type'],
-        'description' => isset($skin['description']) ? $skin['description'] : $defaults['description'],
-        'features' => isset($skin['features']) ? $skin['features'] : $defaults['features'],
-        'templates' => isset($skin['templates']) ? $skin['templates'] : $defaults['templates'],
-        'group' => !empty($skin['group']) && !empty($skinset['options']['groups'][$skin['group']]) ? $skin['group'] : $defaults['group'],
-        'options' => isset($skin['options']) ? $skin['options'] : $defaults['options'],
-        'stylesheets' => isset($skin['stylesheets']) ? $skin['stylesheets'] : $defaults['stylesheets'],
-        'scripts' => isset($skin['scripts']) ? $skin['scripts'] : $defaults['scripts'],
-        'weight' => isset($skin['weight']) ? $skin['weight'] : $defaults['weight'],
-      );
-
-      // Give the stylesheets proper path information.
-      $skinset['skins'][$id]['stylesheets'] = _skinr_add_path_to_files($skinset['skins'][$id]['stylesheets'], $path_root, 'css');
-
-      // Give the scripts proper path information.
-      $skinset['skins'][$id]['scripts'] = _skinr_add_path_to_files($skinset['skins'][$id]['scripts'], $path_root, 'js');
-
-      foreach ($skinset['skins'][$id]['options'] as $oid => $option) {
-        if (isset($option['stylesheets'])) {
-          $skinset['skins'][$id]['options'][$oid]['stylesheets'] = _skinr_add_path_to_files($option['stylesheets'], $path_root, 'css');
-        }
-        if (isset($option['scripts'])) {
-          $skinset['skins'][$id]['options'][$oid]['scripts'] = _skinr_add_path_to_files($option['scripts'], $path_root, 'js');
-        }
-      }
+function skinr_status_default($default_status = 0) {
+  $status = array();
+  foreach (list_themes() as $name => $theme) {
+    if (!$theme->status) {
+      continue;
     }
+    $status[$name] = $default_status;
   }
+  return $status;
+}
 
-  return $skinset;
+/**
+ * Get a list of plugin hooks.
+ *
+ * @return
+ *   An array of hook details keyed by hook name. The hook details contain the
+ *   following keys:
+ *   - 'type': Available options are 'module' or 'theme'.
+ *   - 'name': The name of the owner module or theme of this plugin.
+ *   - 'plugin': The name of the skins plugin.
+ *   - 'path': This plugin's path.
+ */
+function skinr_plugin_hooks() {
+  // @todo Load the include files and get an array of hooks; we need to
+  //       know which module and which plugin comprises the hook.
+  $hooks = array();
+  return $hooks;
 }
 
 /**
- * Helper function to prepend a path to an array of stylesheets or scripts in a .info file.
+ * Helper function to prepend a path to an array of stylesheets or scripts
+ * in a .info file. If the url is absolute (e.g. the url start with 'http://')
+ * the path does not get prepended.
  *
  * @param $files
  *   A an array of filenames that need the path prepended.
+ *   @todo Adjust docs to account for arrays instead of filenames.
  * @param $path
  *   The path to prepend.
- * @param $type
- *   Either 'css' or 'js', depending on which files you wish to retrieve from
- *   these skins.
- *
- * @return
- *    An array of files with the root path added.
  */
-function _skinr_add_path_to_files($files, $path, $type) {
-  if ($type == 'css') {
-    $pathed_stylesheets = array();
-    foreach ($files as $media => $stylesheets) {
-      foreach ($stylesheets as $stylesheet) {
-        $pathed_stylesheets[$media][$stylesheet] = $path . '/' . $stylesheet;
+function _skinr_add_path_to_files(&$files, $path) {
+  foreach ($files as $key => $file) {
+    if (is_array($file)) {
+      if (strpos($file[0], 'http://') === 0) {
+        continue;
       }
+      $files[$key][0] = $path . '/' . $file[0];
     }
-    return $pathed_stylesheets;
-  }
-  elseif ($type == 'js') {
-    $pathed_scripts = array();
-    foreach ($files as $script) {
-      $pathed_scripts[$script] = $path . '/' . $script;
+    else {
+      if (strpos($file, 'http://') === 0) {
+        continue;
+      }
+      $files[$key] = $path . '/' . $file;
     }
-    return $pathed_scripts;
   }
-
-  return FALSE;
 }
 
 /**
- * Helper function to process an array of skins.
+ * Parse a skins array as returned from a skins plugin. This function inserts
+ * any missing defaults and updates the stylsheet and script paths to be
+ * relative to drupal's root.
  *
- * @return
- *    An array of skinsets.
+ * @param $skins
+ *   A skins array as returned from a skins plugin.
+ * @param $source
+ *   An array with the following keys:
+ *   - 'type': Available options are 'module' or 'theme'.
+ *   - 'name': The name of the owner module or theme of this plugin.
+ *   - 'plugin': The name of the skins plugin.
+ *   - 'path': This plugin's path.
  */
-function skinr_skinsets() {
-  $skinsets = &drupal_static(__FUNCTION__, array());
-
-  if (!empty($skinsets)) {
-    $result = db_query("SELECT * FROM {skinr_skinsets}");
-    foreach ($result as $skinset) {
-      if (file_exists($skinset->filename)) {
-        $skinset->info = unserialize($skinset->info);
-        $skinsets[$skinset->name] = $skinset;
-      }
-    }
-
-    $themes = list_themes();
-    $default_status = array();
-    foreach ($themes as $theme) {
-      $default_status[$theme->name] = $theme->name;
-    }
-
-    foreach ($skinsets as $key => $skinset) {
-      if (isset($themes[$key])) {
-        $skinset->type = 'theme';
-        $skinset->status = !empty($theme->status) ? 1 : 0;
+function skinr_parse_skins(&$skins, $source) {
+  foreach ($skins as $name => $skin) {
+    // Merge in defaults.
+    $skins[$name] = array_merge(skinr_skin_default(), $skins[$name]);
+
+    // Merge in source information.
+    $skins[$name]['source'] = $source;
+
+    // Merge in default statuses for all themes.
+    $skins[$name]['status'] = array_merge(skinr_status_default($skins[$name]['default_status']), $skins[$name]['status']);
+
+    // @todo Apply overridden statuses. This will need to be loaded from
+    //       database.
+
+    // Add path to stylesheets.
+    _skinr_add_path_to_files($skins[$name]['stylesheets'], $source['path']);
+    // Add path to scripts.
+    _skinr_add_path_to_files($skins[$name]['scripts'], $source['path']);
+
+    // @todo If we change 'options' to 'variants' we'll have to update this part.
+    foreach ($skins[$name]['options'] as $oid => $option) {
+      // Add path to stylesheets.
+      if (isset($option['stylesheets'])) {
+        _skinr_add_path_to_files($skins[$name]['options'][$oid]['stylesheets'], $source['path']);
       }
-      else {
-        $skinset->type = 'skinset';
+      // Add path to scripts.
+      if (isset($option['scripts'])) {
+        _skinr_add_path_to_files($skins[$name]['options'][$oid]['scripts'], $source['path']);
       }
 
-      // @todo Allow skins to inherit from other skins.
-
-      $additional = _skinr_skinset($skinset);
-      $skinset->options = $additional['options'];
-      $skinset->skins = $additional['skins'];
-
-      $statuses = skinr_skinset_statuses($skinset->name);
-      foreach ($skinset->skins as $skin_name => $skin) {
-        $skinset->skins[$skin_name]['status'] = !empty($statuses[$skin_name]) ? $statuses[$skin_name] : $default_status;
+      // Validate class by running it through drupal_html_class().
+      if (!is_array($skins[$name]['options'][$oid]['class'])) {
+        $skins[$name]['options'][$oid]['class'] = array($skins[$name]['options'][$oid]['class']);
+      }
+      foreach ($skins[$name]['options'][$oid]['class'] as $key => $class) {
+        $skins[$name]['options'][$oid]['class'][$key] = drupal_html_class($class);
       }
     }
-  }
 
-  return $skinsets;
+    // @todo Should we add 'group' => CSS_THEME and 'group' => JS_THEME to
+    //       stylesheet and script options?
+  }
 }
 
 /**
- * Return an array of statuses of each skin in a skinset for each theme.
- *
- * @param $skinset_name
- *   The name of the skinset of which to load the statuses.
+ * Helper function to process an array of skins.
  *
  * @return
- *   Array of statuses for individual skins in a skinset.
+ *    An array of skinsets.
  */
-function skinr_skinset_statuses($skinset_name) {
-  $statuses = &drupal_static(__FUNCTION__, array());
+function skinr_skins_load() {
+  $skins = &drupal_static(__FUNCTION__);
+
+  if (!isset($skins)) {
+    // Set skins to an array to avoid errors down the line if no skins
+    // are found.
+    $skins = array();
+
+    // Load skins from hook_skinr_skins().
+    $hooks = skinr_plugin_hooks();
+    foreach ($hooks as $hook => $source) {
+      // @todo Update the hook name once we settle on one.
+      $function = $hook . '_skinr_skins';
+      $result = $function();
+      if (isset($result)) {
+        if (!is_array($result)) {
+          $result = array($result);
+        }
 
-  if (empty($statuses[$skinset_name])) {
-    $statuses[$skinset_name] = array();
+        // Make any programatic changes.
+        skinr_parse_skins($result, $source);
 
-    $result = db_query("SELECT * FROM {skinr_skins} WHERE name = :name", array(':name' => $skinset_name));
-    foreach ($result as $skinr_skin) {
-      $statuses[$skinset_name][$skinr_skin->skin] = unserialize($skinr_skin->status);
+        $skins = array_merge_recursive($skins, $result);
+      }
     }
+
+    // Allow modules to alter skins through hook_skinr_skins_alter().
+    drupal_alter('skinr_skins', $skins);
   }
 
-  return $statuses[$skinset_name];
+  return $skins;
 }
 
 /**
- * Themes are allowed to set Skinr skins in their .info files.
+ * Load all skinr groups.
  *
  * @return
- *    An array of skinsets keyed by themename.
- *
- * @todo Use DB caching. No need to keep processing things every page load.
+ *    An array of groups.
  */
-function skinr_skin_data() {
-  $cache = &drupal_static(__FUNCTION__);
-
-  if (is_null($cache)) {
-    $skinsets = skinr_skinsets();
+function skinr_groups_load() {
+  $groups = &drupal_static(__FUNCTION__);
 
-    // Need to merge all skins skinsets into a single list of skins.
-    // Also merge in the groups information.
-    $additional_skins = array();
+  if (!isset($groups)) {
+    // Set groups to an array to avoid errors down the line if no groups
+    // are found.
     $groups = array();
-    foreach ($skinsets as $key => $skinset) {
-      if ($skinset->type == 'skinset') {
-        if (!empty($skinset->skins) && $skinset->status == 1) {
-          $additional_skins += $skinset->skins;
-        }
-        if (!empty($skinset->options['groups'])) {
-          $groups += $skinset->options['groups'];
+
+    // Load skins from hook_skinr_groups().
+    $hooks = skinr_plugin_hooks();
+    foreach ($hooks as $hook => $source) {
+      // @todo Update the hook name once we settle on one.
+      $function = $hook . '_skinr_groups';
+      $result = $function();
+      if (isset($result)) {
+        if (!is_array($result)) {
+          $result = array($result);
         }
-      }
-    }
 
-    // Merge the additional skins into each theme, even if that theme has no
-    // skinr data.
-    $themes = list_themes();
-    foreach ($themes as $theme) {
-      if ($theme->status != 1) {
-        continue;
-      }
+        // Make any programatic changes.
+        // Merge in defaults.
+        $result = array_merge(skinr_group_default(), $result);
 
-      if (!empty($skinsets[$theme->name])) {
-        $cache[$theme->name] = $skinsets[$theme->name];
-        $cache[$theme->name]->skins += $additional_skins;
-        $cache[$theme->name]->options['groups'] += $groups;
-      }
-      else {
-        $cache[$theme->name] = new stdClass();
-        $cache[$theme->name]->name = $theme->name;
-        $cache[$theme->name]->status = 1;
-        $cache[$theme->name]->type = 'theme';
-        $cache[$theme->name]->skins = $additional_skins;
-        $cache[$theme->name]->options = array('groups' => $groups);
+        $groups = array_merge_recursive($groups, $result);
       }
-    }
+
+    // Allow modules to alter groups through hook_skinr_groups_alter().
+    drupal_alter('skinr_groups', $skins);
   }
 
-  return $cache;
+  return $groups;
 }
 
 /**
@@ -890,10 +806,7 @@ function skinr_fetch_config() {
 
   if (is_null($cache)) {
     $cache = module_invoke_all('skinr_config');
-    foreach (module_implements('skinr_config_alter') as $module) {
-      $function = $module . '_skinr_config_alter';
-      $function($cache);
-    }
+    drupal_alter('skinr_config', $cache);
   }
 
   return $cache;
diff --git skinr_ui.admin.inc skinr_ui.admin.inc
index 9d7b676..bf3853e 100644
--- skinr_ui.admin.inc
+++ skinr_ui.admin.inc
@@ -613,7 +613,7 @@ function skinr_ui_sort_by_info_name($a, $b) {
 function skinr_ui_admin_skinsets_submit($form, &$form_state) {
   // Store list of previously enabled themes and disable all themes.
   $old_skinset_list = $new_skinset_list = array();
-  foreach (skinr_skinsets() as $skinset) {
+  foreach (skinr_skins_load() as $skinset) {
     if ($skinset->status) {
       $old_skinset_list[] = $skinset->name;
     }
@@ -730,7 +730,7 @@ function theme_skinr_ui_admin_skinsets_incompatible($variables) {
 function skinr_ui_admin_skinsets_settings($form, $form_state, $skinset_name) {
   $form = array();
 
-  $skinsets = skinr_skinsets();
+  $skinsets = skinr_skins_load();
   if (!empty($skinsets[$skinset_name])) {
     $skinset = $skinsets[$skinset_name];
 
diff --git skinr_ui.module skinr_ui.module
index 1f1afb5..cf7bba5 100644
--- skinr_ui.module
+++ skinr_ui.module
@@ -63,13 +63,13 @@ function skinr_ui_menu() {
   // drupal_uninstall_modules() invokes hook_menu() in disabled modules and does
   // not respect module dependencies. Therefore, uninstalling both Skinr UI and
   // Skinr at the same time is leading to a database error, since
-  // skinr_skinsets() tries to load data from tables that have been deleted
+  // skinr_skins_load() tries to load data from tables that have been deleted
   // already.
   // @see http://drupal.org/node/151452
   // @see http://drupal.org/node/320303
   $skinsets = array();
   if (in_array('skinr', module_list())) {
-    $skinsets = skinr_skinsets();
+    $skinsets = skinr_skins_load();
   }
   foreach ($skinsets as $skinset) {
     $items['admin/appearance/skinr/skins/settings/' . $skinset->name] = array(
@@ -392,15 +392,16 @@ function skinr_ui_form_alter(&$form, $form_state, $form_id) {
   }
   
   $skinr_config = skinr_fetch_config();
-  $info = skinr_skin_data();
+  $skins = skinr_skins_load();
+  $groups = skinr_groups_load();
 
-  foreach ($skinr_config as $module => $settings) {
-    if (isset($settings['form'][$form_id])) {
+  foreach ($skinr_config as $module => $module_settings) {
+    if (isset($module_settings['form'][$form_id])) {
       if (!empty($form['skinr']) && $form['skinr']['module']['#value'] !== $module) {
         continue;
       }
 
-      $form_settings = array_merge(_skinr_fetch_config_defaults('form'), $settings['form'][$form_id]);
+      $form_settings = array_merge(_skinr_fetch_config_defaults('form'), $module_settings['form'][$form_id]);
 
       // Check for access.
       if (!skinr_handler('access_handler', 'access skinr', $form_settings['access_handler'], $form, $form_state)) {
@@ -491,74 +492,70 @@ function skinr_ui_form_alter(&$form, $form_state, $form_id) {
 
         // Create individual widgets for each skin.
         $template_options = array();
-        if (isset($info[$theme->name]->skins)) {
-          foreach ($info[$theme->name]->skins as $skin_id => $skin) {
-            // Check if this skin is disabled.
-            if (empty($skin['status'][$theme->name])) {
-              continue;
-            }
+        foreach ($skins as $skin_name => $skin) {
+          // Check if this skin is disabled.
+          if (empty($skin['status'][$theme->name])) {
+            continue;
+          }
 
-            // Check if this skin applies to this hook.
-            if (!is_array($skin['features']) || (!in_array('*', $skin['features']) && !_skinr_is_featured($preprocess_hooks, $skin['features']))) {
-              continue;
-            }
+          // Check if this skin applies to this hook.
+          if (!is_array($skin['features']) || (!in_array('*', $skin['features']) && !_skinr_is_featured($preprocess_hooks, $skin['features']))) {
+            continue;
+          }
 
-            // Create widget.
-            switch ($skin['type']) {
-              case 'checkboxes':
-                $field = array(
-                  '#type' => 'checkboxes',
-                  '#multiple' => TRUE,
-                  '#title' => t($skin['title']),
-                  '#options' => skinr_ui_info_options_to_form_options($skin['options']),
-                  '#default_value' => isset($defaults[$skin_id]) ? $defaults[$skin_id] : array(),
-                  '#description' => t($skin['description']),
-                  '#weight' => isset($skin['weight']) ? $skin['weight'] : NULL,
-                );
-                break;
-              case 'radios':
-                $field = array(
-                  '#type' => 'radios',
-                  '#title' => t($skin['title']),
-                  '#options' => array_merge(array('' => '&lt;none&gt;'), skinr_ui_info_options_to_form_options($skin['options'])),
-                  '#default_value' => isset($defaults[$skin_id]) ? $defaults[$skin_id] : '',
-                  '#description' => t($skin['description']),
-                  '#weight' => isset($skin['weight']) ? $skin['weight'] : NULL,
-                );
-                break;
-              case 'select':
-                $field = array(
-                  '#type' => 'select',
-                  '#title' => t($skin['title']),
-                  '#options' => array_merge(array('' => '<none>'), skinr_ui_info_options_to_form_options($skin['options'])),
-                  '#default_value' => isset($defaults[$skin_id]) ? $defaults[$skin_id] : '',
-                  '#description' => t($skin['description']),
-                  '#weight' => isset($skin['weight']) ? $skin['weight'] : NULL,
-                );
-                break;
-            }
-            if (empty($skin['group'])) {
-              $form['skinr_settings'][$module . '_group'][$theme->name]['widgets'][$skin_id] = $field;
-            }
-            else {
-              if (!isset($form['skinr_settings'][$module . '_group'][$theme->name]['widgets'][$skin['group']])) {
-                $group = $info[$theme->name]->options['groups'][$skin['group']];
-                $form['skinr_settings'][$module . '_group'][$theme->name]['widgets'][$skin['group']] = array(
-                  '#type' => 'fieldset',
-                  '#title' => t($group['title']),
-                  '#description' => t($group['description']),
-                  '#collapsible' => $group['collapsible'],
-                  '#collapsed' => $group['collapsed'],
-                  '#weight' => isset($group['weight']) ? $group['weight'] : NULL,
-                );
-              }
-              $form['skinr_settings'][$module . '_group'][$theme->name]['widgets'][$skin['group']][$skin_id] = $field;
+          // Create widget.
+          switch ($skin['type']) {
+            case 'checkboxes':
+              $field = array(
+                '#type' => 'checkboxes',
+                '#multiple' => TRUE,
+                '#title' => t($skin['title']),
+                '#options' => skinr_ui_info_options_to_form_options($skin['options']),
+                '#default_value' => isset($defaults[$skin_name]) ? $defaults[$skin_name] : array(),
+                '#description' => t($skin['description']),
+                '#weight' => isset($skin['weight']) ? $skin['weight'] : NULL,
+              );
+              break;
+            case 'radios':
+              $field = array(
+                '#type' => 'radios',
+                '#title' => t($skin['title']),
+                '#options' => array_merge(array('' => '&lt;none&gt;'), skinr_ui_info_options_to_form_options($skin['options'])),
+                '#default_value' => isset($defaults[$skin_name]) ? $defaults[$skin_name] : '',
+                '#description' => t($skin['description']),
+                '#weight' => isset($skin['weight']) ? $skin['weight'] : NULL,
+              );
+              break;
+            case 'select':
+              $field = array(
+                '#type' => 'select',
+                '#title' => t($skin['title']),
+                '#options' => array_merge(array('' => '<none>'), skinr_ui_info_options_to_form_options($skin['options'])),
+                '#default_value' => isset($defaults[$skin_name]) ? $defaults[$skin_name] : '',
+                '#description' => t($skin['description']),
+                '#weight' => isset($skin['weight']) ? $skin['weight'] : NULL,
+              );
+              break;
+          }
+          if (empty($skin['group'])) {
+            $form['skinr_settings'][$module . '_group'][$theme->name]['widgets'][$skin_name] = $field;
+          }
+          else {
+            if (!isset($form['skinr_settings'][$module . '_group'][$theme->name]['widgets'][$skin['group']])) {
+              $group = $groups[$skin['group']];
+              $form['skinr_settings'][$module . '_group'][$theme->name]['widgets'][$skin['group']] = array(
+                '#type' => 'fieldset',
+                '#title' => t($group['title']),
+                '#description' => t($group['description']),
+                '#weight' => isset($group['weight']) ? $group['weight'] : NULL,
+              );
             }
-
-            // Prepare templates.
-            $templates = skinr_ui_info_templates_filter($skin['templates'], $preprocess_hooks);
-            $template_options = array_merge($template_options, skinr_ui_info_templates_to_form_options($templates));
+            $form['skinr_settings'][$module . '_group'][$theme->name]['widgets'][$skin['group']][$skin_name] = $field;
           }
+
+          // Prepare templates.
+          $templates = skinr_ui_info_templates_filter($skin['templates'], $preprocess_hooks);
+          $template_options = array_merge($template_options, skinr_ui_info_templates_to_form_options($templates));
         }
 
         // Check for access.
@@ -616,11 +613,11 @@ function skinr_ui_form_validate($form, &$form_state) {
   $skinr_config = skinr_fetch_config();
 
   $error = FALSE;
-  foreach ($skinr_config as $module => $settings) {
-    if (isset($settings['form'][$form_id]) && isset($form_state['values']['skinr_settings'][$module . '_group'])) {
+  foreach ($skinr_config as $module => $module_settings) {
+    if (isset($module_settings['form'][$form_id]) && isset($form_state['values']['skinr_settings'][$module . '_group'])) {
       foreach ($form_state['values']['skinr_settings'][$module . '_group'] as $theme_name => $theme) {
         if (isset($theme['_additional'])) {
-          $form_settings = array_merge(_skinr_fetch_config_defaults('form'), $settings['form'][$form_id]);
+          $form_settings = array_merge(_skinr_fetch_config_defaults('form'), $module_settings['form'][$form_id]);
 
           // Validate additional classes field.
           if (preg_match('/[^a-zA-Z0-9\-\_\s]/', $theme['_additional'])) {
@@ -636,15 +633,11 @@ function skinr_ui_form_validate($form, &$form_state) {
 
   // Undo any grouping to ease processing on submit.
   if (!$error) {
-    $info = skinr_skin_data();
-    foreach ($skinr_config as $module => $settings) {
-      if (isset($settings['form'][$form_id]) && isset($form_state['values']['skinr_settings'][$module . '_group'])) {
+    $groups = skinr_groups_load();
+    foreach ($skinr_config as $module => $module_settings) {
+      if (isset($module_settings['form'][$form_id]) && isset($form_state['values']['skinr_settings'][$module . '_group'])) {
         foreach ($form_state['values']['skinr_settings'][$module . '_group'] as $theme_name => $theme) {
-          if (empty($info[$theme_name]->options['groups'])) {
-            continue;
-          }
-
-          foreach ($info[$theme_name]->options['groups'] as $group_name => $group) {
+          foreach ($groups as $group_name => $group) {
             if (!empty($theme['widgets'][$group_name]) && is_array($theme['widgets'][$group_name])) {
               $group_values = $theme['widgets'][$group_name];
               unset($form_state['values']['skinr_settings'][$module . '_group'][$theme_name]['widgets'][$group_name]);
@@ -665,9 +658,9 @@ function skinr_ui_form_submit($form, &$form_state) {
   $skinr_config = skinr_fetch_config();
   $current_theme = skinr_current_theme(TRUE);
 
-  foreach ($skinr_config as $module => $settings) {
-    if (isset($settings['form'][$form_id])) {
-      $form_settings = array_merge(_skinr_fetch_config_defaults('form'), $settings['form'][$form_id]);
+  foreach ($skinr_config as $module => $module_settings) {
+    if (isset($module_settings['form'][$form_id])) {
+      $form_settings = array_merge(_skinr_fetch_config_defaults('form'), $module_settings['form'][$form_id]);
       skinr_handler('submit_handler', '', $form_settings['submit_handler'], $form, $form_state, $module, $form_settings);
 
       // Keep looping, there might be other modules that implement the same form_id.
@@ -686,12 +679,12 @@ function skinr_ui_preprocess(&$variables, $hook) {
     $original_hook = $theme_registry[$hook]['original hook'];
   }
 
-  foreach ($skinr_config as $module => $settings) {
-    if (!empty($settings['preprocess'][$original_hook])) {
+  foreach ($skinr_config as $module => $module_settings) {
+    if (!empty($module_settings['preprocess'][$original_hook])) {
 
       // Set contextual links.
-      if (!empty($settings['contextual_links'][$original_hook])) {
-        if ($contextual_links = skinr_handler('contextual_links', '', $settings['contextual_links'][$original_hook]['contextual_links_handler'], $variables)) {
+      if (!empty($module_settings['contextual_links'][$original_hook])) {
+        if ($contextual_links = skinr_handler('contextual_links', '', $module_settings['contextual_links'][$original_hook]['contextual_links_handler'], $variables)) {
           skinr_ui_contextual_links($variables, $original_hook, $contextual_links);
         }
       }
@@ -770,8 +763,8 @@ function _skinr_ui_ajax_id() {
  */
 function skinr_ui_info_options_to_form_options($options) {
   $form_options = array();
-  foreach ($options as $option) {
-    $form_options[$option['class']] = t($option['label']);
+  foreach ($options as $option_name => $option) {
+    $form_options[$option_name] = t($option['label']);
   }
   return $form_options;
 }
