diff --git a/Solr_Base_Query.php b/Solr_Base_Query.php
index 57f02fe..40ded03 100644
--- a/Solr_Base_Query.php
+++ b/Solr_Base_Query.php
@@ -164,21 +164,24 @@ class SolrBaseQuery extends SolrFilterSubQuery implements DrupalSolrQueryInterfa
   protected $solr;
   // The array keys must always be real Solr index fields.
   protected $available_sorts;
+  /**
+   * The query name is used to construct a searcher string. Typically something like 'apachesolr'
+   */
+  protected $name;
 
   // Makes sure we always have a valid sort.
   protected $solrsort = array('#name' => 'score', '#direction' => 'desc');
 
   /**
+   * @param $name
+   *   A name (namespce) for this query.  Typically 'apachesolr'.
+   *
    * @param $solr
    *   An instantiated DrupalApacheSolrService Object.
    *   Can be instantiated from apachesolr_get_solr().
    *
-   * @param $keys
-   *   The string that a user would type into the search box. Suitable input
-   *   may come from search_get_keys().
-   *
-   * @param $fq
-   *   Array of filter queries.
+   * @param $params
+   *   Array of params to initialize the object (typically 'q' and 'fq').
    *
    * @param $sortstring
    *   Visible string telling solr how to sort - added to GET query params.
@@ -186,11 +189,11 @@ class SolrBaseQuery extends SolrFilterSubQuery implements DrupalSolrQueryInterfa
    * @param $base_path
    *   The search base path (without the keywords) for this query, without trailing slash.
    */
-  function __construct($solr, $keys = '', $fq = array(), $sortstring = '', $base_path = '') {
+  function __construct($name, $solr, array $params = array(), $sortstring = '', $base_path = '') {
     parent::__construct();
+    $this->name = $name;
     $this->solr = $solr;
-    $this->addParam('q', trim($keys));
-    $this->addParam('fq', $fq);
+    $this->addParams($params);
     $this->available_sorts = $this->defaultSorts();
     $this->sortstring = trim($sortstring);
     $this->parseSortstring();
@@ -207,6 +210,20 @@ class SolrBaseQuery extends SolrFilterSubQuery implements DrupalSolrQueryInterfa
     );
   }
 
+  /**
+   * Get query name.
+   */
+  public function getName() {
+    return $this->name;
+  }
+
+  /**
+   * Get query searcher name (for facetapi, views, pages, etc).
+   */
+  public function getSearcher() {
+    return $this->name . '@' . $this->solr->getServerId();
+  }
+
   protected $single_value_params = array(
     'q' => TRUE,    // http://wiki.apache.org/solr/SearchHandler#q
     'q.op' => TRUE, // http://wiki.apache.org/solr/SearchHandler#q.op
@@ -261,7 +278,7 @@ class SolrBaseQuery extends SolrFilterSubQuery implements DrupalSolrQueryInterfa
     if ($name == 'fq') {
       return $this->rebuildFq();
     }
-    $empty = isset($single_value_params[$name]) ? NULL : array();
+    $empty = isset($this->single_value_params[$name]) ? NULL : array();
     return isset($this->params[$name]) ? $this->params[$name] : $empty;
   }
 
@@ -315,7 +332,7 @@ class SolrBaseQuery extends SolrFilterSubQuery implements DrupalSolrQueryInterfa
       if (is_array($value)) {
         $value = end($value);
       }
-      $this->params[$name] = $value;
+      $this->params[$name] = trim($value);
       return $this;
     }
     // We never actually populate $this->params['fq'].  Instead
diff --git a/apachesolr.admin.inc b/apachesolr.admin.inc
index 5be4d85..637959a 100644
--- a/apachesolr.admin.inc
+++ b/apachesolr.admin.inc
@@ -790,12 +790,12 @@ function apachesolr_mlt_block_form($delta = NULL) {
   $form['restrictions']['mlt_custom_filters'] = array(
     '#type' => 'textfield',
     '#title' => t('Additional Query'),
-    '#description' => t("An additional query, in Lucene syntax, which will further filter the similarity suggestions. Ex. 'label:strategy' will filter related content further to only those with strategy in the title. Likewise 'content:HDTV^3' will boost the term HDTV by a factor of 3. Here are some more examples:") .
+    '#description' => t("A query, in Lucene syntax, which will further filter the similarity suggestions. For example, 'label:strategy' will filter related content further to only those with strategy in the title. Here are some more examples:") .
                         '<ul>
                             <li>ss_language:fr</li>
-                            <li>tid:5 OR tid 7</li>
+                            <li>tid:(5 OR 7)</li>
                             <li>ds_created:[2009-05-01T23:59:59Z TO 2009-07-28T12:30:00Z]</li>
-                            <li>-is_uid:0 AND -is_uid:1</li>
+                            <li>-is_uid:0, -is_uid:1</li>
                         </ul>',
     '#required' => FALSE,
     '#default_value' => $block['mlt_custom_filters'],
diff --git a/apachesolr.module b/apachesolr.module
index dbfc7be..5c3ebde 100644
--- a/apachesolr.module
+++ b/apachesolr.module
@@ -937,13 +937,17 @@ function apachesolr_block_view($delta = '') {
     return $suggestions;
   }
   elseif (apachesolr_has_searched() && !apachesolr_suppress_blocks() && $delta == 'sort') {
-    // Get the query and response. Without these no blocks make sense.
-    $response = apachesolr_static_response_cache();
+
+    $response = NULL;
+    $query = apachesolr_current_query();
+    if ($query) {
+      // Get the query and response. Without these no blocks make sense.
+      $response = apachesolr_static_response_cache($query->getSearcher());
+    }
     if (empty($response) || ($response->response->numFound < 2)) {
       return;
     }
 
-    $query = apachesolr_current_query();
     $sorts = $query->getAvailableSorts();
 
     // Get the current sort as an array.
@@ -1067,7 +1071,7 @@ function apachesolr_form_facetapi_facet_settings_form_alter(&$form, $form_state)
  *
  * Example:
  *
- * function my_module_apachesolr_modify_query($query, $caller) {
+ * function my_module_apachesolr_modify_query($query) {
  *   // I only want to see articles by the admin!
  *   $query->add_filter("is_uid", 1);
  *
@@ -1076,17 +1080,15 @@ function apachesolr_form_facetapi_facet_settings_form_alter(&$form, $form_state)
  * @return
  *   TRUE to abort the current query, FALSE otherwise.
  */
-function apachesolr_modify_query(DrupalSolrQueryInterface $query, $caller) {
+function apachesolr_modify_query(DrupalSolrQueryInterface $query) {
   if (empty($query)) {
     // This should only happen if Solr is not set up - avoids fatal errors.
     return TRUE;
   }
 
-  // Call the hooks first because otherwise any modifications to the
-  // $query object don't end up in the $params.
   foreach (module_implements('apachesolr_modify_query') as $module) {
     $function_name = $module . '_apachesolr_modify_query';
-    if ($function_name($query, $caller)) {
+    if ($function_name($query)) {
       // Someone pulled the ejection handle.
       return TRUE;
     }
@@ -1325,14 +1327,12 @@ function apachesolr_server_status($url, $class = NULL) {
 }
 
 /**
- * Execute a search based on a query object.
+ * Execute a keyword search based on a query object.
  *
  * Normally this function is used with the default (dismax) handler for keyword
  * searches. The $final_query that's returned will have been modified by
  * both hook_apachesolr_prepare_query() and hook_apachesolr_modify_query().
  *
- * @param $caller
- *   String, name of the calling module or function for use as a cache namespace.
  * @param $current_query
  *   A query object from apachesolr_drupal_query().  It will be modified by
  *   hook_apachesolr_prepare_query() and then cached in apachesolr_current_query().
@@ -1343,13 +1343,14 @@ function apachesolr_server_status($url, $class = NULL) {
  *
  * @throws Exception
  */
-function apachesolr_do_query($caller, DrupalSolrQueryInterface $current_query, $page = 0) {
+function apachesolr_do_query(DrupalSolrQueryInterface $current_query, $page = 0) {
   // Allow modules to alter the query prior to statically caching it.
   // This can e.g. be used to add available sorts.
+  $searcher = $current_query->getSearcher();
 
   if (module_exists('facetapi')) {
     // Gets enabled facets, adds filter queries to $params.
-    $adapter = facetapi_adapter_load('apachesolr@' . $current_query->solr('getServerId'));
+    $adapter = facetapi_adapter_load($searcher);
     if ($adapter) {
       $adapter->addFacetsFilters($current_query);
     }
@@ -1357,27 +1358,21 @@ function apachesolr_do_query($caller, DrupalSolrQueryInterface $current_query, $
 
   foreach (module_implements('apachesolr_prepare_query') as $module) {
     $function_name = $module . '_apachesolr_prepare_query';
-    $function_name($current_query, $caller);
+    $function_name($current_query);
   }
 
   // Cache the original query. Since all the built queries go through
   // this process, all the hook_invocations will happen later
-  $query = apachesolr_current_query($current_query, $caller);
+  $query = apachesolr_current_query($current_query);
 
   // This hook allows modules to modify the query and params objects.
-  $eject = apachesolr_modify_query($query, $caller);
+  $eject = apachesolr_modify_query($query);
 
   // A module implementing hook_apachesolr_modify_query() aborted the search.
   if ($eject) {
     return array(NULL, array());
   }
   $query->addParam('start', $page * $query->getParam('rows'));
-  // Final chance for the caller to modify the query. The signature
-  // is: CALLER_finalize_query($query);
-  $function = $caller . '_finalize_query';
-  if (function_exists($function)) {
-    $function($query);
-  }
 
   $keys = $query->getParam('q');
 
@@ -1406,7 +1401,7 @@ function apachesolr_do_query($caller, DrupalSolrQueryInterface $current_query, $
   $response = $query->search($keys);
   // The response is cached so that it is accessible to the blocks and anything
   // else that needs it beyond the initial search.
-  apachesolr_static_response_cache($response, $caller);
+  apachesolr_static_response_cache($searcher, $response);
   return array($query, $response);
 }
 
@@ -1414,29 +1409,29 @@ function apachesolr_do_query($caller, DrupalSolrQueryInterface $current_query, $
  * It is important to hold on to the Solr response object for the duration of the
  * page request so that we can use it for things like building facet blocks.
  *
- * @todo reverse the order of parameters in future branches.
+ * @param $searcher
+ *   Name of the searcher - e.g. from $query->getSearcher().
  */
-function apachesolr_static_response_cache($response = NULL, $namespace = 'apachesolr_search') {
+function apachesolr_static_response_cache($searcher, $response = NULL) {
   static $_response = array();
 
   if (is_object($response)) {
-    $_response[$namespace] = clone $response;
+    $_response[$searcher] = clone $response;
   }
-  if (!isset($_response[$namespace])) {
-    $_response[$namespace] = NULL;
+  if (!isset($_response[$searcher])) {
+    $_response[$searcher] = NULL;
   }
-  return $_response[$namespace];
+  return $_response[$searcher];
 }
 
 /**
  * Factory function for query objects.
  *
- * @param $keys
- *   The string that a user would type into the search box. Suitable input
- *   may come from search_get_keys().
- *
- * @param $filters
- *   Key and value pairs that are applied as a filter query.
+ * @param $name
+ *   The search name, used for finding the correct blocks and other config.
+ *   Typically "apachesolr".
+ * @param $params
+ *   Array of params , such as 'q', 'fq' to be applied.
  * @param $solrsort
  *   Visible string telling solr how to sort.
  * @param $base_path
@@ -1449,28 +1444,26 @@ function apachesolr_static_response_cache($response = NULL, $namespace = 'apache
  *
  * @throws Exception
  */
-function apachesolr_drupal_query($keys = '', $fq = array(), $solrsort = '', $base_path = '', $solr = NULL) {
+function apachesolr_drupal_query($name, $params = array(), $solrsort = '', $base_path = '', $solr = NULL) {
   $class = variable_get('apachesolr_query_class', 'SolrBaseQuery');
 
   if (empty($solr)) {
     $solr = apachesolr_get_solr();
   }
-  return new $class($solr, $keys, $fq, $solrsort, $base_path);
+  return new $class($name, $solr, $params, $base_path);
 }
 
 /**
- * Static getter/setter for the current query
- *
- * @todo reverse the order of parameters in future branches.
+ * Static getter/setter for the current query. Only set once per page.
  */
-function apachesolr_current_query(DrupalSolrQueryInterface $query = NULL, $namespace = 'apachesolr_search') {
-  static $saved_query = array();
+function apachesolr_current_query(DrupalSolrQueryInterface $query = NULL) {
+  static $saved_query = NULL;
 
   if (is_object($query)) {
-    $saved_query[$namespace] = clone $query;
+    $saved_query = clone $query;
   }
 
-  return is_object($saved_query[$namespace]) ? clone $saved_query[$namespace] : NULL;
+  return is_object($saved_query) ? clone $saved_query : NULL;
 }
 
 /**
@@ -1922,36 +1915,35 @@ function apachesolr_mlt_suggestions($settings, $id, $solr = NULL) {
       'mlt_boost' => 'mlt.boost',
       'mlt_qf' => 'mlt.qf',
     );
-    // We can optionally specify a Solr object.
-    $query = apachesolr_drupal_query('id:' . $id, '', '', '', $solr);
-    $query->params = array(
+    $params = array(
+      'q' => 'id:' . $id,
       'qt' => 'mlt',
       'fl' => 'entity_id,entity_type,label,path,url',
       'mlt.fl' => implode(',', $settings['mlt_fl']),
       'start' => 0,
       'rows' => $settings['num_results'],
     );
+    // We can optionally specify a Solr object.
+    $query = apachesolr_drupal_query('apachesolr_mlt', $params, '', '', $solr);
 
     foreach ($fields as $form_key => $name) {
       if (!empty($settings[$form_key])) {
-        $query->params[$name] = $settings[$form_key];
+        $query->addParam($name, $settings[$form_key]);
       }
     }
 
     $type_filters = array();
     if (is_array($settings['mlt_type_filters'])) {
-      foreach ($settings['mlt_type_filters'] as $type_filter) {
-        $type_filters[] = "bundle:{$type_filter}";
-      }
-      $query->params['fq']['mlt'][] = '(' . implode(' OR ', $type_filters) . ') ';
+      $query->addFilter('bundle', '(' . implode(' OR ', $settings['mlt_type_filters']) . ') ');
     }
 
     if ($custom_filters = $settings['mlt_custom_filters']) {
-      $query->params['fq']['mlt'][] = $custom_filters;
+      // @todo - fix the settings form to take a comma-delimited set of filters.
+      $query->addFilter('', $custom_filters);
     }
 
     // This hook allows modules to modify the query object.
-    $eject = apachesolr_modify_query($query, 'apachesolr_mlt');
+    $eject = apachesolr_modify_query($query);
     if ($eject) {
       return;
     }
@@ -2117,9 +2109,9 @@ function apachesolr_l($text, $path, $options = array()) {
   }
 
   // Retain GET parameters that ApacheSolr knows nothing about.
-  $query = apachesolr_current_query();
-  $get = array_diff_key($_GET, array('q' => 1, 'page' => 1), $options['query'], $query->getUrlQueryvalues());
-  $options['query'] += $get;
+  //$query = apachesolr_current_query();
+  //$get = array_diff_key($_GET, array('q' => 1, 'page' => 1), $options['query'], $query->getUrlQueryvalues());
+  //$options['query'] += $get;
 
   return '<a href="' . check_url(url($path, $options)) . '"' . drupal_attributes($options['attributes']) . '>' . ($options['html'] ? $text : check_plain(html_entity_decode($text))) . '</a>';
 }
diff --git a/apachesolr_search.admin.inc b/apachesolr_search.admin.inc
index 4876fdc..0ca8cf1 100644
--- a/apachesolr_search.admin.inc
+++ b/apachesolr_search.admin.inc
@@ -6,6 +6,286 @@
  */
 
 /**
+ *
+ */
+function apachesolr_search_page_list_page() {
+  $build = array();
+
+  // Build the sortable table header.
+  $header = array(
+    'label' => array('data' => t('Name'), 'field' => 's.label'),
+    'path' => array('data' => t('Path'), 'field' => 's.search_path'),
+    'server' => array('data' => t('Server'), 'field' => 'ser.server_name'),
+    'operations' => array('data' => t('Operations'), 'colspan' => '2'),
+  );
+
+  // Initializes the search page query.
+  $query = db_select('apachesolr_search_page', 's')
+    ->fields('s', array('label', 'name', 'page_title', 'description', 'search_path'))
+    ->extend('PagerDefault')
+    ->extend('TableSort')
+    ->limit(20)
+    ->orderByHeader($header);
+
+  $query->addField('ser', 'name', 'server_name');
+
+  // Joins on the server table.
+  $query->leftJoin('apachesolr_server', 'ser', 's.server_id = ser.server_id');
+
+  $rows = array();
+  foreach ($query->execute() as $record) {
+    $row = array();
+
+    $row[] = check_plain($record->label);
+
+    $row[] = array(
+      'data' => array(
+        '#type' => 'link',
+        '#title' => $record->search_path,
+        '#href' => $record->search_path,
+      ),
+    );
+
+    $row[] = check_plain($record->server_name);
+
+    // Operations
+    $row[] = array('data' => l(t('Edit'), 'admin/config/search/apachesolr/search-pages/' . $record->name . '/edit'));
+    $row[] = array('data' => l(t('Delete'), 'admin/config/search/apachesolr/search-pages/' . $record->name . '/delete'));
+      
+    $rows[] = $row;
+  }
+
+  $build['list'] = array(
+    '#theme' => 'table',
+    '#header' => $header,
+    '#rows' => $rows,
+    '#empty' => t('No available search pages.'),
+  );
+
+  return $build;
+}
+
+/**
+ *
+ */
+function apachesolr_search_page_settings_form($form, &$form_state, $search_page = NULL) {
+
+  // Initializes form with common settings.
+  $form['label'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Name'),
+    '#description' => '',
+    '#required' => TRUE,
+    '#size' => 30,
+    '#maxlength' => 32,
+    '#weight' => -50,
+    '#default_value' => !empty($search_page->label) ? $search_page->label : '',
+  );
+
+  $form['name'] = array(
+    '#type' => 'machine_name',
+    '#maxlength' => 32,
+    '#required' => TRUE,
+    '#machine_name' => array(
+      'exists' => 'apachesolr_search_page_exists',
+      'source' => array('label'),
+    ),
+    '#description' => '',
+    '#weight' => -40,
+    '#default_value' => !empty($search_page->name) ? $search_page->name : '',
+    '#disabled' => !empty($search_page),
+  );
+
+  $form['info']['description'] = array(
+    '#title' => t('Description'),
+    '#type' => 'textfield',
+    '#required' => FALSE,
+    '#maxlength' => 255,
+    '#description' => '',
+    '#default_value' => !empty($search_page->description) ? $search_page->description : '',
+  );
+
+  $form['info']['search_path'] = array(
+    '#title' => t('Path'),
+    '#type' => 'textfield',
+    '#required' => TRUE,
+    '#maxlength' => 255,
+    '#description' => t('For example: search/my-search-page. Search keywords will appear at the end of the path.'),
+    '#default_value' => !empty($search_page->search_path) ? $search_page->search_path : '',
+  );
+
+  $form['info']['filters'] = array(
+    '#title' => t('Default filters'),
+    '#type' => 'textfield',
+    '#required' => FALSE,
+    '#maxlength' => 255,
+    '#description' => t('A comma-separated list of lucene filter queries to apply by default. E.g. "bundle:blog, is_uid:(1 OR 2 OR 3)"'),
+    '#default_value' => !empty($search_page->settings['fq'])  ? implode(', ', $search_page->settings['fq']) : '',
+  );
+
+  $form['info']['page_title'] = array(
+    '#title' => t('Title'),
+    '#type' => 'textfield',
+    '#required' => TRUE,
+    '#maxlength' => 255,
+    '#description' => '',
+    '#default_value' => !empty($search_page->page_title) ? $search_page->page_title : '',
+  );
+
+  // Sets the descriptions and button text.
+  $form['label']['#description'] = t('The human-readable name of the search page configuration.');
+  $form['name']['#description'] = t('A unique machine-readable name for the search page configuration. It must only contain lowercase letters, numbers, and underscores.');
+  $form['info']['description']['#description'] = t('The description of the search page configuration.');
+
+  $id = variable_get('apachesolr_default_server', 'solr');
+  $servers = apachesolr_load_all_servers();
+
+  $options = array();
+  foreach ($servers as $id => $server) {
+    $options[$id] = $server['name'];
+  }
+
+  $form['info']['server_id'] = array(
+    '#title' => t('Server'),
+    '#type' => 'select',
+    '#options' => $options,
+    '#default_value' => !empty($search_page->server_id) ? $search_page->server_id : NULL,
+    '#description' => t('The server that is searched by this search page.'),
+    '#required' => TRUE,
+    '#weight' => -30,
+  );
+
+  $form['actions'] = array(
+    '#type' => 'actions',
+    '#weight' => 20,
+  );
+
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+
+  $form['actions']['submit_list'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save and go back to list'),
+  );
+
+  $form['actions']['cancel'] = array(
+    '#type' => 'link',
+    '#title' => t('Cancel'),
+    '#href' => 'admin/config/search/apachesolr/search-pages',
+  );
+
+  $form['#submit'][] = 'apachesolr_search_page_settings_form_submit';
+
+  return $form;
+}
+
+function apachesolr_search_page_settings_form_validate($form, &$form_state) {
+  // Performs basic validation of the menu path.
+  if (url_is_external($form_state['values']['search_path'])) {
+    form_set_error('search_path', t('Path must be local.'));
+  }
+  $form_state['values']['search_path'] = trim($form_state['values']['search_path'], '/');
+  if (empty($form_state['values']['search_path'])) {
+    form_set_error('search_path', t('Path required.'));
+  }
+}
+
+/**
+ * Processes apachesolr_search_page_settings_form form submissions.
+ */
+function apachesolr_search_page_settings_form_submit($form, &$form_state) {
+  $settings = array();
+  if ($form_state['values']['filters']) {
+    foreach(explode(',', $form_state['values']['filters']) as $string) {
+      $string = trim($string);
+      // Minimal validation.  ':' must exist and can't be the 1st char..
+      if (strpos($string, ':')) {
+        $settings['fq'][] = $string;
+      }
+    }
+  }
+  db_merge('apachesolr_search_page')
+    ->key(array('name' => $form_state['values']['name']))
+    ->fields(array(
+      'label' => $form_state['values']['label'],
+      'name' => $form_state['values']['name'],
+      'description' => $form_state['values']['description'],
+      'server_id' => $form_state['values']['server_id'],
+      'search_path' => $form_state['values']['search_path'],
+      'page_title' => $form_state['values']['page_title'],
+      'settings' => serialize($settings),
+    ))
+    ->execute();
+
+  // Saves our values in the database, sets redirect path on success.
+  drupal_set_message(t('The configuration options have been saved.'));
+
+  if (t('Save and go back to list') == $form_state['clicked_button']['#value']) {
+      $form_state['redirect'] = 'admin/config/search/apachesolr/search-pages';
+  }
+
+  // Menu rebuild needed to pick up search path.
+  menu_rebuild();
+}
+
+/**
+ * Deletes a single search page configuration.
+ */
+function apachesolr_search_delete_search_page_confirm($form, &$form_state, $search_page) {
+
+  // Sets values required for deletion.
+  $form['name'] = array('#type' => 'value', '#value' => $search_page->name);
+  $form['label'] = array('#type' => 'value', '#value' => $search_page->label);
+
+  // Sets the message, or the title of the page.
+  $message = t(
+    'Are you sure you want to delete the %label search page configuration?',
+    array('%label' => $form['label']['#value'])
+  );
+
+  // Builds caption.
+  $caption = '<p>';
+  $caption .= t(
+    'The %label search page configuration will be deleted.',
+    array('%label' => $form['label']['#value'])
+  );
+  $caption .= '</p>';
+  $caption .= '<p><strong>' . t('This action cannot be undone.') . '</strong></p>';
+
+  // Finalizes and returns the confirmation form.
+  $return_path = 'admin/config/search/apachesolr/search-pages';
+  $button_text = t('Delete configuration');
+  return confirm_form($form, $message, $return_path, $caption, $button_text);
+}
+
+/**
+ * Process content type delete confirm submissions.
+ */
+function apachesolr_search_delete_search_page_confirm_submit($form, &$form_state) {
+  // Deletes the index configuration settings.
+  // @todo Invoke a hook that allows backends and indexers to delete their stuff.
+  db_delete('apachesolr_search_page')
+    ->condition('name', $form_state['values']['name'])
+    ->execute();
+
+  // Sets message, logs action.
+  drupal_set_message(t(
+    'The %label search page configuration has been deleted.',
+    array('%label' => $form_state['values']['label'])
+  ));
+  watchdog('apachesolr_search', 'Deleted search page configuration "@name".', array('@name' => $form_state['values']['name']), WATCHDOG_NOTICE);
+
+  // Rebuilds the menu cache.
+  menu_rebuild();
+
+  // Returns back to search page list page.
+  $form_state['redirect'] = 'admin/config/search/apachesolr/search-pages';
+}
+
+
+/**
  * Menu callback - the settings form.
  */
 function apachesolr_search_settings_page($server_id = NULL) {
diff --git a/apachesolr_search.info b/apachesolr_search.info
index c77bddd..31e69de 100644
--- a/apachesolr_search.info
+++ b/apachesolr_search.info
@@ -8,3 +8,4 @@ core = 7.x
 files[] = apachesolr_search.install
 files[] = apachesolr_search.module
 files[] = apachesolr_search.admin.inc
+files[] = apachesolr_search.pages.inc
diff --git a/apachesolr_search.install b/apachesolr_search.install
index d76c8f7..9f4f73f 100644
--- a/apachesolr_search.install
+++ b/apachesolr_search.install
@@ -15,6 +15,87 @@ function apachesolr_search_enable() {
 }
 
 /**
+ * Implements hook_schema().
+ */
+function apachesolr_search_schema() {
+  $schema = array();
+
+  $schema['apachesolr_search_page'] = array(
+    'description' => 'Apache Solr Search search page settings.',
+    'export' => array(
+      'key' => 'name',
+      'identifier' => 'searcher',
+      'default hook' => 'apachesolr_search_default_searchers',
+      'status' => 'apachesolr_search_page_status',
+      'api' => array(
+        'owner' => 'apachesolr_search',
+        'api' => 'apachesolr_search_defaults',
+        'minimum_version' => 3,
+        'current_version' => 3,
+      ),
+      'export callback' => 'apachesolr_search_page_settings_export',
+    ),
+    'fields' => array(
+      'name' => array(
+        'description' => 'The machine readable name of the search page.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'label' => array(
+        'description' => 'The human readable name of the search page.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'description' => array(
+        'description' => 'The description of the search page.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'search_path' => array(
+        'description' => 'The path to the search page.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'page_title' => array(
+        'description' => 'The title of the search page.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'server_id' => array(
+        'description' => 'The machine name of the server.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'settings' => array(
+        'description' => 'Serialized storage of general settings.',
+        'type' => 'text',
+        'serialize' => TRUE,
+      ),
+    ),
+    'primary key' => array('name'),
+    'indexes' => array(
+      'server_id' => array('server_id'),
+    ),
+  );
+
+  return $schema;
+}
+
+
+
+/**
  * Implements hook_uninstall().
  */
 function apachesolr_search_uninstall() {
@@ -51,3 +132,10 @@ function apachesolr_search_update_7000() {
   variable_del('apachesolr_search_make_default');
 }
 
+/**
+ * Add apachesolr_search_page table.
+ */
+function apachesolr_search_update_7001() {
+  drupal_install_schema('apachesolr_search');
+}
+
diff --git a/apachesolr_search.module b/apachesolr_search.module
index 94bbbd2..5752817 100644
--- a/apachesolr_search.module
+++ b/apachesolr_search.module
@@ -34,6 +34,37 @@ function apachesolr_search_help($section) {
  * Implements hook_menu().
  */
 function apachesolr_search_menu() {
+  $items['admin/config/search/apachesolr/search-pages'] = array(
+    'title'            => 'Search Pages',
+    'description'      => t('Configure search pages.'),
+    'page callback'    => 'apachesolr_search_page_list_page',
+    'access arguments' => array('administer search'),
+    'type'             => MENU_LOCAL_TASK,
+    'file'             => 'apachesolr_search.admin.inc',
+  );
+  $items['admin/config/search/apachesolr/search-pages/add'] = array(
+    'title'            => 'Add search page configuration',
+    'page callback'    => 'drupal_get_form',
+    'page arguments'   => array('apachesolr_search_page_settings_form'),
+    'access arguments' => array('administer search'),
+    'type'             => MENU_LOCAL_ACTION,
+    'file'             => 'apachesolr_search.admin.inc',
+  );
+  $items['admin/config/search/apachesolr/search-pages/%apachesolr_search_page/edit'] = array(
+    'title' => 'Edit search page configuration',
+    'page callback'    => 'drupal_get_form',
+    'page arguments'   => array('apachesolr_search_page_settings_form', 5),
+    'access arguments' => array('administer search'),
+    'file'             => 'apachesolr_search.admin.inc',
+  );
+  $items['admin/config/search/apachesolr/search-pages/%apachesolr_search_page/delete'] = array(
+    'title'            => 'Delete search page configuration',
+    'load arguments'   => array('apachesolr_search_page'),
+    'page callback'    => 'drupal_get_form',
+    'page arguments'   => array('apachesolr_search_delete_search_page_confirm', 5),
+    'access arguments' => array('administer search'),
+    'file'             => 'apachesolr_search.admin.inc',
+  );
   $items['admin/config/search/apachesolr/query-fields'] = array(
     'title'            => 'Search fields',
     'page callback'    => 'apachesolr_search_settings_page',
@@ -51,9 +82,65 @@ function apachesolr_search_menu() {
     'file'             => 'apachesolr_search.admin.inc',
   );
 
+  try {
+    // Gets search pages directly from the index.
+    // @todo Honor "enabled" settings?
+    $result = db_select('apachesolr_search_page', 's')
+      ->fields('s', array('name', 'search_path', 'page_title'))
+      ->execute();
+  }
+  catch (Exception $e) {
+    watchdog_exception('apachesolr_search', $e);
+    $result = array();
+  }
+
+  // Gets default search information.
+  $default_info = search_get_default_module_info();
+
+  // Iterates over search pages, builds menu items.
+  foreach ($result as $record) {
+    // Parses search path into it's various parts, builds menu items dependent
+    // on whether %keys is in the path.
+    $parts = explode('/', $record->search_path);
+    $keys_pos = count($parts);
+    // Tests whether we are simulating a core search tab.
+    $core_search = ($parts[0] == 'search');
+
+    $items[$record->search_path] = array(
+      'title' => $record->page_title,
+      'page callback' => 'apachesolr_search_user_defined_search_page',
+      'page arguments' => array($record->name, ''),
+      'access arguments' => array('search content'),
+      'type' => ($core_search) ? MENU_LOCAL_TASK : MENU_SUGGESTED_ITEM,
+      'file' => 'apachesolr_search.pages.inc',
+    );
+
+    $items[$record->search_path . '/%menu_tail'] = array(
+      'title' => $record->page_title,
+      'load arguments' => array('%map', '%index'),
+      'page callback' => 'apachesolr_search_user_defined_search_page',
+      'page arguments' => array($record->name, $keys_pos),
+      'access arguments' => array('search content'),
+      'type' => MENU_LOCAL_TASK,
+      'file' => 'apachesolr_search.pages.inc',
+    );
+    if ($core_search) {
+      $items[$record->search_path . '/%menu_tail']['tab_root'] = 'search/' . $default_info['path'] . '/%';
+      $items[$record->search_path . '/%menu_tail']['tab_parent'] = 'search/' . $default_info['path'];
+    }
+  }
+
   return $items;
 }
 
+function apachesolr_search_page_load($name) {
+  $page = db_query('SELECT * FROM {apachesolr_search_page} s WHERE s.name = :name', array(':name' => $name))->fetchObject();
+  if ($page) {
+    $page->settings = unserialize($page->settings);
+  }
+  return $page; 
+}
+
 /**
  * Implements hook_cron(). Indexes nodes.
  */
@@ -110,7 +197,7 @@ function apachesolr_search_search_execute($keys = NULL, $conditions = NULL) {
   try {
     if (!$keys && !$conditions && ($empty_search_behavior == 'browse' || $empty_search_behavior == 'blocks')) {
       // Pass empty search behavior as string on to apachesolr_search_search_page()
-      apachesolr_search_run_empty('search/' . arg(1));
+      apachesolr_search_run_empty('apachesolr', 'search/' . arg(1));
       $results['apachesolr_search_browse'] = $empty_search_behavior;
       if ($empty_search_behavior == 'browse') {
         // Hide sidebar blocks for content-area browsing instead.
@@ -118,7 +205,7 @@ function apachesolr_search_search_execute($keys = NULL, $conditions = NULL) {
       }
     }
     else {
-      $results = apachesolr_search_run($keys, $filters, $solrsort, 'search/' . arg(1), pager_find_page());
+      $results = apachesolr_search_run('apachesolr', array('q' => $keys, 'fq' => $filters), $solrsort, 'search/' . arg(1), pager_find_page());
     }
     return $results;
   }
@@ -224,18 +311,19 @@ function apachesolr_search_page_browse($empty_search_behavior) {
 /**
  * Execute a search with zero results rows so as to populate facets.
  */
-function apachesolr_search_run_empty($base_path = '', $caller = 'apachesolr_search') {
-  $query = apachesolr_drupal_query('', array(), '', $base_path);
+function apachesolr_search_run_empty($name, $base_path = '') {
+  $query = apachesolr_drupal_query($name, array(), '', $base_path);
   $query->addParam('rows', '0');
-  list($final_query, $response) = apachesolr_do_query($caller, $query, 0);
+  list($final_query, $response) = apachesolr_do_query($query, 0);
   apachesolr_has_searched(TRUE);
 }
 
 /**
  * Execute a search results based on keyword, filter, and sort strings.
  *
- * @param $keys
- * @param $filterstring
+ * @param $name
+ * @param $params
+ *   Array - 'q' is the keywords to search.
  * @param $solrsort
  * @param $base_path
  *   For constructing filter and sort links. Leave empty unless the links need to point somewhere
@@ -248,13 +336,13 @@ function apachesolr_search_run_empty($base_path = '', $caller = 'apachesolr_sear
  *
  * @throws Exception
  */
-function apachesolr_search_run($keys, $fq = array(), $solrsort = '', $base_path = '', $page = 0, $caller = 'apachesolr_search') {
+function apachesolr_search_run($name, array $params = array(), $solrsort = '', $base_path = '', $page = 0, $solr = NULL) {
   // This is the object that knows about the query coming from the user.
-  $query = apachesolr_drupal_query($keys, $fq, $solrsort, $base_path);
+  $query = apachesolr_drupal_query($name, $params, $solrsort, $base_path, $solr);
 
   apachesolr_search_basic_params($query);
   apachesolr_search_add_boost_params($query);
-  if ($keys) {
+  if ($query->getParam('q')) {
     apachesolr_search_highlighting_params($query);
     if (!$query->getParam('hl.fl')) {
       $qf = array();
@@ -275,7 +363,7 @@ function apachesolr_search_run($keys, $fq = array(), $solrsort = '', $base_path
     // No highlighting, use the teaser as a snippet.
     $query->addParam('fl', 'teaser');
   }
-  list($final_query, $response) = apachesolr_do_query($caller, $query, $page);
+  list($final_query, $response) = apachesolr_do_query($query, $page);
   apachesolr_has_searched(TRUE);
 
   return apachesolr_search_process_response($response, $final_query);
@@ -540,6 +628,13 @@ function apachesolr_search_node_result($doc, &$result, &$extra) {
 }
 
 /**
+ * Returns whether a search page exists. 
+ */
+function apachesolr_search_page_exists($search_page_name) {
+  return db_query('SELECT 1 FROM {apachesolr_search_page} WHERE name = :name', array(':name' => $search_page_name))->fetchField();
+}
+
+/**
  * Template preprocess for apachesolr search results.
  *
  * We need to add additional entity/bundle-based templates
@@ -556,12 +651,15 @@ function apachesolr_search_preprocess_search_result(&$variables) {
 function apachesolr_search_preprocess_search_results(&$variables) {
   // If this is a solr search, expose more data to themes to play with.
   if ($variables['module'] == 'apachesolr_search') {
-    $variables['response'] = apachesolr_static_response_cache();
+    $query = apachesolr_current_query();
+    if ($query) {
+      $variables['query'] = $query;
+      $variables['response'] = apachesolr_static_response_cache($query->getSearcher());
+    }
     if (empty($variables['response'])) {
       $variables['description'] = '';
       return;
     }
-    $variables['query'] = apachesolr_current_query();
     $total = $variables['response']->response->numFound;
     $params = $variables['query']->getParams();
 
@@ -649,11 +747,12 @@ function apachesolr_search_block_info() {
 function apachesolr_search_block_view($delta = '') {
   if (apachesolr_has_searched() && !apachesolr_suppress_blocks()) {
     // Get the query and response. Without these no blocks make sense.
-    $response = apachesolr_static_response_cache();
+    if ($query = apachesolr_current_query()) {
+      $response = apachesolr_static_response_cache($query->getSearcher());
+    }
     if (empty($response)) {
       return;
     }
-    $query = apachesolr_current_query();
 
     switch ($delta) {
       case 'currentsearch':
@@ -676,9 +775,11 @@ function apachesolr_search_form_search_form_alter(&$form, $form_state) {
     $apachesolr_has_searched = apachesolr_has_searched();
 
     $queryvalues = array();
+    $searcher = NULL;
     if ($apachesolr_has_searched) {
       $query = apachesolr_current_query();
       $queryvalues = $query->getUrlQueryvalues();
+      $searcher = $query->getSearcher();
     }
 
     $form['basic']['apachesolr_search']['#tree'] = TRUE;
@@ -699,13 +800,12 @@ function apachesolr_search_form_search_form_alter(&$form, $form_state) {
       );
     }
 
-    if (variable_get('apachesolr_search_spellcheck', TRUE) && $apachesolr_has_searched && ($response = apachesolr_static_response_cache())) {
+    if (variable_get('apachesolr_search_spellcheck', TRUE) && $apachesolr_has_searched && ($response = apachesolr_static_response_cache($searcher))) {
       // Get spellchecker suggestions into an array.
       if (isset($response->spellcheck->suggestions) && $response->spellcheck->suggestions) {
         $suggestions = get_object_vars($response->spellcheck->suggestions);
         if ($suggestions) {
           // Get the original query and replace words.
-          $query = apachesolr_current_query();
 
           foreach ($suggestions as $word => $value) {
             $replacements[$word] = $value->suggestion[0];
@@ -928,3 +1028,4 @@ function apachesolr_search_currentsearch_block($response, DrupalSolrQueryInterfa
   }
 }
 
+
diff --git a/apachesolr_search.pages.inc b/apachesolr_search.pages.inc
new file mode 100644
index 0000000..5d88df3
--- /dev/null
+++ b/apachesolr_search.pages.inc
@@ -0,0 +1,83 @@
+<?php
+
+/**   
+ * @file
+ *   Provides the page callback for user defined search pages.
+ */ 
+
+/**
+ * Returns search results on user defined search pages.
+ */
+function apachesolr_search_user_defined_search_page($page_id, $keys = '') {
+  $search_page = apachesolr_search_page_load($page_id);
+  $build = array();
+  $filters = isset($search_page->settings['fq']) ? $search_page->settings['fq'] : array();
+  $solrsort = isset($_GET['solrsort']) ? $_GET['solrsort'] : '';
+
+  try {
+    $solr = apachesolr_get_solr($search_page->server_id);
+    $results = apachesolr_search_run('apachesolr', array('q' => $keys, 'fq' => $filters), $solrsort, 'search/' . arg(1), pager_find_page(), $solr);
+
+    // Adds the search form to the page.
+    $build['search_form'] = drupal_get_form('apachesolr_search_user_defined_search_form', $search_page, $keys);
+    // Adds search results to the render array.
+    $build['search_results'] = array(
+      '#theme' => 'search_results',
+      '#results' => $results,
+      '#module' => 'apachesolr_search',
+    );
+  }
+  catch (Exception $e) {
+    watchdog('Apache Solr', nl2br(check_plain($e->getMessage())), NULL, WATCHDOG_ERROR);
+    apachesolr_failure(t('Solr search'), $keys);
+  }
+
+  return $build;
+}
+
+/**
+ * Search for placed on user defined search pages.
+ */
+function apachesolr_search_user_defined_search_form($form, &$form_state, $search_page, $keys = '') {
+  // Loads the core Search CSS file, use the core search module's classes.
+  drupal_add_css(drupal_get_path('module', 'search') . '/search.css');
+  $form['#id'] = 'search-form';
+  $form['#attributes']['class'][] = 'search-form';
+
+  $form['#search_page'] = $search_page;
+
+  $form['basic'] = array(
+    '#type' => 'container',
+    '#attributes' => array('class' => array('container-inline')),
+  );
+
+  $form['basic']['keys'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Enter terms'), 
+    '#default_value' => $keys,
+    '#size' => 20,
+    '#maxlength' => 255,
+  );
+
+  $form['basic']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Search'),
+  );
+
+  return $form;
+}
+
+/**
+ * Processes apachesolr_search_user_defined_search_form submissions.
+ */
+function apachesolr_search_user_defined_search_form_submit(&$form, &$form_state) {
+  $page = $form['#search_page'];
+
+  $redirect = $page->search_path;
+  if (strlen($form_state['values']['keys'])) {
+    $redirect .= '/' . $form_state['values']['keys'];
+  }
+
+  // Redirects to path set in configuration.
+  $form_state['redirect'] = $redirect;
+}
diff --git a/plugins/facetapi/adapter.inc b/plugins/facetapi/adapter.inc
index e806d44..2b3d385 100644
--- a/plugins/facetapi/adapter.inc
+++ b/plugins/facetapi/adapter.inc
@@ -80,7 +80,11 @@ class ApacheSolrFacetapiAdapter extends FacetapiAdapter {
    * Returns a boolean flagging whether $this->_searcher executed a search.
    */
   public function searchExecuted() {
-    return apachesolr_has_searched();
+    // Initial check - has ANY solr query run.
+    $this_has_searched = apachesolr_has_searched();
+    // Secondary check - do we have results for this searcher?
+    $this_has_searched = $this_has_searched && apachesolr_static_response_cache($this->getSearcher());
+    return $this_has_searched;
   }
 
   public function suppressOutput($realm_name) {
@@ -88,7 +92,7 @@ class ApacheSolrFacetapiAdapter extends FacetapiAdapter {
     if ($realm_name == 'block') {
       $flag = apachesolr_suppress_blocks();
     }
-    return $flag || !apachesolr_has_searched();
+    return $flag || !$this->searchExecuted();
   }
 
   /**
diff --git a/plugins/facetapi/query_type_date.inc b/plugins/facetapi/query_type_date.inc
index cd19060..b76a676 100644
--- a/plugins/facetapi/query_type_date.inc
+++ b/plugins/facetapi/query_type_date.inc
@@ -107,7 +107,7 @@ class ApacheSolrFacetapiDate extends FacetapiQueryTypeDate implements FacetapiQu
   public function build() {
 
     // Initializes build and gets static response.
-    if (!$response = apachesolr_static_response_cache()) {
+    if (!$response = apachesolr_static_response_cache($this->adapter->getSearcher())) {
       return array();
     }
     $build = array();
diff --git a/plugins/facetapi/query_type_term.inc b/plugins/facetapi/query_type_term.inc
index 5718fd9..c2fe5c7 100644
--- a/plugins/facetapi/query_type_term.inc
+++ b/plugins/facetapi/query_type_term.inc
@@ -46,7 +46,7 @@ class ApacheSolrFacetapiTerm extends FacetapiQueryType implements FacetapiQueryT
    */
   public function build() {
     $build = array();
-    if ($response = apachesolr_static_response_cache()) {
+    if ($response = apachesolr_static_response_cache($this->adapter->getSearcher())) {
       if (isset($response->facet_counts->facet_fields->{$this->facet['field']})) {
         $values = (array) $response->facet_counts->facet_fields->{$this->facet['field']};
         foreach ($values as $value => $count) {
