diff --git a/feeds_ui/feeds_ui.admin.inc b/feeds_ui/feeds_ui.admin.inc
index 8c31e85fac27298103dfcb5729668ac477468553..30e7c8c39753d77727f6180416bc6bcf1504fec7 100644
--- a/feeds_ui/feeds_ui.admin.inc
+++ b/feeds_ui/feeds_ui.admin.inc
@@ -64,7 +64,13 @@ function feeds_ui_build_create_form(&$form_state) {
     );
   }
   else {
-    $form += _feeds_ui_config_form();
+    feeds_include('feed');
+    $feed = feeds_get_feed($form_state['storage']['id']);
+    $form['settings'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Basic configuration'),
+    );
+    $form['settings'] += $feed->configForm($form_state);
     $form['submit'] = array(
       '#type' => 'submit',
       '#value' => t('Create'),
@@ -73,6 +79,24 @@ function feeds_ui_build_create_form(&$form_state) {
   return $form;
 }
 
+/**
+ * Validation handler for feeds_build_create_form().
+ */
+function feeds_ui_build_create_form_validate($form, &$form_state) {
+  ctools_include('export');
+  if (isset($form_state['values']['id'])) {
+    if (ctools_export_load_object('feeds_configuration', 'conditions', array('id' => $form_state['values']['id'], 'class' => 'Feed'))) {
+      form_set_error('id', t('Id is taken.'));
+    }
+  }
+  elseif (isset($form_state['storage']['id'])) {
+    if (ctools_export_load_object('feeds_configuration', 'conditions', array('id' => $form_state['storage']['id'], 'class' => 'Feed'))) {
+      form_set_error('id', t('Id is taken.'));
+      drupal_goto('admin/build/feeds/create');
+    }
+  }
+}
+
 /**
  * Submit handler for feeds_build_create_form().
  */
@@ -81,9 +105,9 @@ function feeds_ui_build_create_form_submit($form, &$form_state) {
     $form_state['storage']['id'] = $form_state['values']['id'];
   }
   else {
-    // Build and save feed.
-    feeds_include('feed');
-    $feed = new Feed($form_state['storage']['id'], $form_state['values']);
+    // Save feed.
+    $feed = feeds_get_feed($form_state['storage']['id']);
+    $feed->addConfig($form_state['values']);
     $feed->save();
     drupal_set_message(t('Created configuration'));
 
@@ -97,7 +121,12 @@ function feeds_ui_build_create_form_submit($form, &$form_state) {
  * Edit an existing configuration.
  */
 function feeds_ui_build_edit_form(&$form_state, $feed) {
-  $form = _feeds_ui_config_form($feed);
+  $form['#feed'] = $feed;
+  $form['settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Basic configuration'),
+  );
+  $form['settings'] += $feed->configForm($form_state);
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Save'),
@@ -105,14 +134,19 @@ function feeds_ui_build_edit_form(&$form_state, $feed) {
   return $form;
 }
 
+/**
+ * Validation handler for feeds_ui_build_edit_form().
+ */
+function feeds_ui_build_edit_form_validate($form, &$form_state) {
+  $form['#feed']->configFormValidate($form, &$form_state);
+}
+
 /**
  * Submit handler for feeds_ui_build_edit_form().
  */
 function feeds_ui_build_edit_form_submit($form, &$form_state) {
-  $feed = $form['#feed'];
-  $form['#feed']->addConfig($form_state['values']);
-  $form['#feed']->save();
-    drupal_set_message(t('Saved configuration'));
+  $form['#feed']->configFormSubmit($form, &$form_state);
+  drupal_set_message(t('Saved configuration'));
 }
 
 /**
@@ -172,48 +206,3 @@ function feeds_ui_build_plugin_form(&$form_state, $feed) {
   );
   return $form;
 }
-
-/**
- * Helper, build edit UI for a feed. Used for editing and creating.
- * @todo: pull form from feed object.
- */
-function _feeds_ui_config_form($feed = NULL) {
-  $form = array();
-  if ($feed) {
-    $config = $feed->getConfig();
-    $form['#feed'] = $feed;
-  }
-  $form['settings'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Basic configuration'),
-  );
-  $form['settings']['content_type'] = array(
-    '#type' => 'select',
-    '#title' => t('Attach to content type'),
-    '#description' => t('When you attach a configuration to a node, you can use nodes for creating feeds on your site.'),
-    '#options' => array('' => t('None')) + node_get_types('names'),
-    '#default_value' => $config['content_type'],
-  );
-  $form['settings']['source'] = array(
-    '#type' => 'textfield',
-    '#title' => t('URL'),
-    '#description' => t('Enter the URL for this feed @todo: delegate this form to plugin, hide if content type is picked.'),
-    '#default_value' => $config['source']['id'],
-    );
-  $form['settings']['update'] = array(
-    '#type' => 'radios',
-    '#title' => t('Update existing'),
-    '#options' => array(1 => t('Yes'), 0 => t('No')),
-    '#default_value' => $config['update'],
-  );
-  $period = drupal_map_assoc(array(1, 900, 1800, 3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 3628800, 4838400, 7257600, 15724800, 31536000), 'format_interval');
-  $period[FEEDAPI_CRON_NEVER_REFRESH] = t('Do not refresh periodically');
-  $period[1] = t('As often as possible');
-  $form['settings']['refresh_period'] = array(
-    '#type' => 'select',
-    '#title' => t('Minimum refresh period'),
-    '#options' => $period,
-    '#default_value' => $config['refresh_period'],
-  );
-  return $form;
-}
\ No newline at end of file
diff --git a/includes/feed.inc b/includes/feed.inc
index 7fa42fddd9f15353335b43e4200bca64db6e4a91..ea47d9b95a44f1590ba0b79a9b20e32f9a7e46d8 100644
--- a/includes/feed.inc
+++ b/includes/feed.inc
@@ -47,6 +47,42 @@ class Feed extends FeedsConfigurable {
     );
   }
 
+  /**
+   * Override parent::configForm().
+   */
+  public function configForm(&$form_state) {
+    $form = array();
+    $form['content_type'] = array(
+      '#type' => 'select',
+      '#title' => t('Attach to content type'),
+      '#description' => t('When you attach a configuration to a node, you can use nodes for creating feeds on your site.'),
+      '#options' => array('' => t('None')) + node_get_types('names'),
+      '#default_value' => $this->config['content_type'],
+    );
+    $form['source'] = array(
+      '#type' => 'textfield',
+      '#title' => t('URL'),
+      '#description' => t('Enter the URL for this feed @todo: delegate this form to plugin, hide if content type is picked.'),
+      '#default_value' => $config['source']['id'],
+      );
+    $form['update'] = array(
+      '#type' => 'radios',
+      '#title' => t('Update existing'),
+      '#options' => array(1 => t('Yes'), 0 => t('No')),
+      '#default_value' => $this->config['update'],
+    );
+    $period = drupal_map_assoc(array(1, 900, 1800, 3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 3628800, 4838400, 7257600, 15724800, 31536000), 'format_interval');
+    $period[FEEDAPI_CRON_NEVER_REFRESH] = t('Do not refresh periodically');
+    $period[1] = t('As often as possible');
+    $form['refresh_period'] = array(
+      '#type' => 'select',
+      '#title' => t('Minimum refresh period'),
+      '#options' => $period,
+      '#default_value' => $this->config['refresh_period'],
+    );
+    return $form;
+  }
+
   /**
    * Import feed by using configured fetchers, parsers, processors.
    */
@@ -121,7 +157,10 @@ class FeedsConfigurable {
   public function __construct($id, $config = NULL) {
     $this->id = $id;
     if (empty($config)) {
-      $this->load();
+      if (!$this->load()) {
+        // Make sure configuration is populated.
+        $this->config = $this->getDefaultConfig();
+      }
     }
     else {
       $this->config = $config;
@@ -153,6 +192,33 @@ class FeedsConfigurable {
     return FALSE;
   }
 
+  /**
+   * Retrieve this configurable's Id.
+   * 
+   * By convention, a number of configurable objects are associated to each 
+   * other by their common id.
+   */
+  public function getId() {
+    return $this->id;
+  }
+
+  /**
+   * Return default configuration.
+   * 
+   * @return 
+   *   Array where keys are the variable names of the configuration elements and
+   *   values are their default values.
+   */
+  public function getDefaultConfig() {
+    return array();
+  }
+
+  /**
+   * Get configuration.
+   * 
+   * @param $fallback
+   *   Set to false if method should NOT fall back to default configuration.
+   */
   public function getConfig($fallback = TRUE) {
     if ($fallback) {
       return empty($this->config) ? $this->getDefaultConfig() : $this->config;
@@ -160,27 +226,54 @@ class FeedsConfigurable {
     return $this->config;
   }
 
+  /**
+   * Set configuration.
+   * 
+   * @param $config
+   *   Array containing configuration information. Will be filtered by the keys returned by
+   *   getDefaultConfig().
+   */
   public function setConfig($config) {
     $default_keys = $this->getDefaultConfig();
     $this->config = array_intersect_key($config, $default_keys);
   }
 
+  /**
+   * Similar to setConfig but adds to existing configuration.
+   *
+   * @param $config
+   *   Array containing configuration information. Will be filtered by the keys returned by
+   *   getDefaultConfig().
+   */
   public function addConfig($config) {
     $this->config = array_merge($this->config, $config);
     $default_keys = $this->getDefaultConfig();
     $this->config = array_intersect_key($this->config, $default_keys);
   }
 
-  public function getDefaultConfig() {
+  /**
+   * Return configuration form for this object.
+   * 
+   * @return FormAPI style form definition.
+   */
+  public function configForm(&$form_state) {
     return array();
   }
 
-  public function getId() {
-    return $this->id;
+  /**
+   * Validation handler for configForm().
+   *
+   * @return unknown
+   */
+  public function configFormValidate($form, &$form_state) {
   }
 
-  public function form() {
-    return array();
+  /**
+   * Submit handler for configForm().
+   */
+  public function configFormSubmit($form, &$form_state) {
+    $this->addConfig($form_state['values']);
+    $this->save();
   }
 }