diff --git includes/VersioncontrolRepository.php includes/VersioncontrolRepository.php
index 7482a9c..4617c62 100644
--- includes/VersioncontrolRepository.php
+++ includes/VersioncontrolRepository.php
@@ -99,7 +99,7 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
    * The current plugin types(array keys) are:
    * - author_mapper
    * - committer_mapper
-   * - auth_handler
+   * - webviewer_url_handler
    *
    * @var array
    */
@@ -112,6 +112,13 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
    */
   protected $pluginInstances = array();
 
+  /**
+   * The instance for this repository url handler.
+   *
+   * @var VersioncontrolRepositoryUrlHandlerInterface
+   */
+  protected $urlHandler;
+
   protected $defaultCrudOptions = array(
     'update' => array('nested' => TRUE),
     'insert' => array('nested' => TRUE),
@@ -366,24 +373,24 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
    * Convinience method to retrieve url handler.
    */
   public function getUrlHandler() {
-    if (!isset($this->data['versioncontrol']['url_handler'])) {
-      $this->data['versioncontrol']['url_handler'] =
-        new VersioncontrolRepositoryUrlHandler(
-          $this, VersioncontrolRepositoryUrlHandler::getEmpty()
-        );
+    if (!isset($this->urlHandler)) {
+      $plugin = $this->getPlugin('webviewer_url_handler', 'webviewer_url_handlers');
+      $class_name = ctools_plugin_get_class($plugin, 'handler');
+      if (!class_exists($class_name)) {
+        throw new Exception("Plugin 'webviewer_url_handler' of type 'webviewer_url_handlers' does not contain a valid class name in handler slot 'handler'", E_WARNING);
+        return FALSE;
+      }
+      $this->urlHandler = new $class_name(
+        $this, $this->data['versioncontrol']['base_url'], $plugin['url_templates']
+      );
     }
-    return $this->data['versioncontrol']['url_handler'];
+    return $this->urlHandler;
   }
 
   /**
-   * Get an instantiated plugin object based on a requested plugin slot, and the
-   * plugin this repository object has assigned to that slot.
-   *
-   * Internal function - other methods should provide a nicer public-facing
-   * interface. This method exists primarily to reduce code duplication involved
-   * in ensuring error handling and sound loading of the plugin.
+   * Get a ctools plugin based on plugin slot passed.
    */
-  protected function getPluginClass($plugin_slot, $plugin_type, $class_type) {
+  protected function getPlugin($plugin_slot, $plugin_type) {
     ctools_include('plugins');
 
     if (empty($this->plugins[$plugin_slot])) {
@@ -398,6 +405,20 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
       return FALSE;
     }
 
+    return $plugin;
+  }
+
+  /**
+   * Get an instantiated plugin object based on a requested plugin slot, and the
+   * plugin this repository object has assigned to that slot.
+   *
+   * Internal function - other methods should provide a nicer public-facing
+   * interface. This method exists primarily to reduce code duplication involved
+   * in ensuring error handling and sound loading of the plugin.
+   */
+  protected function getPluginClass($plugin_slot, $plugin_type, $class_type) {
+    $plugin = $this->getPlugin($plugin_slot, $plugin_type);
+
     $class_name = ctools_plugin_get_class($plugin, $class_type);
     if (!class_exists($class_name)) {
       throw new Exception("Plugin '$plugin_name' of type '$plugin_type' does not contain a valid class name in handler slot '$class_type'", E_WARNING);
@@ -450,85 +471,40 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
 }
 
 /**
- * Contains the urls mainly for displaying.
+ * Base class for URL handlers.
  */
-class VersioncontrolRepositoryUrlHandler {
+class VersioncontrolRepositoryUrlHandler implements VersioncontrolWebviewerUrlHandlerInterface {
 
   /**
    * Repository where this urls belongs.
    *
-   * @var    VersioncontrolRepository
+   * @var VersioncontrolRepository
    */
   public $repository;
 
   /**
-   * An array of repository viewer URLs.
+   * The first part of the URL that is going to be prepended to each URL
+   * retrieved.
    *
-   * @var    array
+   * @var string
    */
-  public $urls;
+  public $base_url;
 
-  public function __construct($repository, $urls) {
+  /**
+   * An array of template URLs for the web viewer.
+   *
+   * @var array
+   */
+  public $template_urls;
+
+  public function __construct($repository, $base_url, $template_urls) {
     $this->repository = $repository;
-    $this->urls = $urls;
+    $this->base_url = $base_url;
+    $this->template_urls = $template_urls;
   }
 
-  /**
-   * Explain and return and empty array of urls data member.
-   */
-  public static function getEmpty() {
-    return array(
-      /**
-       * The URL of the repository viewer that displays a given commit in the
-       * repository. "%revision" is used as placeholder for the
-       * revision/commit/changeset identifier.
-       */
-      'commit_view'    => '',
-      /**
-       * The URL of the repository viewer that displays the commit log of a
-       * given file in the repository. "%path" is used as placeholder for the
-       * file path, "%revision" will be replaced by the file-level revision
-       * (the one in {versioncontrol_item_revisions}.revision), and "%branch"
-       * will be replaced by the branch name that the file is on.
-       */
-      'file_log_view'  => '',
-      /**
-       * The URL of the repository viewer that displays the contents of a given
-       * file in the repository. "%path" is used as placeholder for the file
-       * path, "%revision" will be replaced by the file-level revision (the one
-       * in {versioncontrol_item_revisions}.revision), and "%branch" will be
-       * replaced by the branch name that the file is on.
-       */
-      'file_view'      => '',
-      /**
-       * The URL of the repository viewer that displays the contents of a given
-       * directory in the repository. "%path" is used as placeholder for the
-       * directory path, "%revision" will be replaced by the file-level revision
-       * (the one in {versioncontrol_item_revisions}.revision - only makes sense
-       * if directories are versioned, of course), and "%branch" will be
-       * replaced by the branch name that the directory is on.
-       */
-      'directory_view' => '',
-      /**
-       * The URL of the repository viewer that displays the diff between two
-       * given files in the repository. "%path" and "%old-path" are used as
-       * placeholders for the new and old paths (for some version control
-       * systems, like CVS, those paths will always be the same).
-       * "%new-revision" and "%old-revision" will be replaced by the
-       * respective file-level revisions (from
-       * {versioncontrol_item_revisions}.revision), and "%branch" will be
-       * replaced by the branch name that the file is on.
-       */
-      'diff'           => '',
-      /**
-       * The URL of the issue tracker that displays the issue/case/bug page of
-       * an issue id which presumably has been mentioned in a commit message.
-       * As issue tracker URLs are likely specific to each repository, this is
-       * also a per-repository setting. (Although... maybe it would make sense
-       * to have per-project rather than per-repository. Oh well.)
-       */
-      'tracker'        => ''
-    );
+  public function getTemplateUrl($name) {
+    return sprintf('%s/%s', $this->baseUrl, $this->template_urls[$name]);
   }
 
   /**
@@ -547,7 +523,7 @@ class VersioncontrolRepositoryUrlHandler {
     if (empty($revision)) {
       return '';
     }
-    return strtr($this->urls['commit_view'], array(
+    return strtr($this->getTemplateUrl('commit_view'), array(
       '%revision' => $revision,
     ));
   }
@@ -571,12 +547,12 @@ class VersioncontrolRepositoryUrlHandler {
     $label = $item->getSelectedLabel();
 
     if (isset($label->type) && $label->type == VERSIONCONTROL_LABEL_BRANCH) {
-      $current_branch = $label['name'];
+      $current_branch = $label->name;
     }
 
-    if (!empty($this->urls['file_log_view'])) {
+    if (!empty($this->template_urls['file_log_view'])) {
       if ($item->isFile()) {
-        return strtr($this->urls['file_log_view'], array(
+        return strtr($this->getTemplateUrl('file_log_view'), array(
           '%path'     => $item->path,
           '%revision' => $item->revision,
           '%branch'   => isset($current_branch) ? $current_branch : '',
@@ -593,6 +569,7 @@ class VersioncontrolRepositoryUrlHandler {
       if (isset($current_branch)) {
         $query['branches'] = $current_branch;
       }
+      // FIXME change this to current view
       return url('commitlog', array(
         'query' => $query,
         'absolute' => TRUE,
@@ -620,12 +597,12 @@ class VersioncontrolRepositoryUrlHandler {
       $current_branch = $label->name;
     }
     $view_url = $item->isFile()
-      ? $this->urls['file_view']
-      : $this->urls['directory_view'];
+      ? $this->getTemplateUrl('file_view')
+      : $this->getTemplateUrl('directory_view');
 
     return strtr($view_url, array(
-      '%path'     => $item['path'],
-      '%revision' => $item['revision'],
+      '%path'     => $item->path,
+      '%revision' => $item->revision,
       '%branch'   => isset($current_branch) ? $current_branch : '',
     ));
   }
@@ -647,14 +624,14 @@ class VersioncontrolRepositoryUrlHandler {
   public function getDiffUrl(&$file_item_new, $file_item_old) {
     $label = $file_item_new->getSelectedLabel();
 
-    if (isset($label['type']) && $label['type'] == VERSIONCONTROL_LABEL_BRANCH) {
-      $current_branch = $label['name'];
+    if (isset($label->type) && $label->type == VERSIONCONTROL_LABEL_BRANCH) {
+      $current_branch = $label->name;
     }
-    return strtr($this->urls['diff'], array(
-      '%path'         => $file_item_new['path'],
-      '%new-revision' => $file_item_new['revision'],
-      '%old-path'     => $file_item_old['path'],
-      '%old-revision' => $file_item_old['revision'],
+    return strtr($this->getTemplateUrl('diff'), array(
+      '%path'         => $file_item_new->path,
+      '%new-revision' => $file_item_new->revision,
+      '%old-path'     => $file_item_old->path,
+      '%old-revision' => $file_item_old->revision,
       '%branch'       => isset($current_branch) ? $current_branch : '',
     ));
   }
@@ -673,6 +650,6 @@ class VersioncontrolRepositoryUrlHandler {
    *   An empty string is returned if no issue tracker URL has been defined.
    */
   public function getTrackerUrl($issue_id) {
-    return strtr($this->urls['tracker'], array('%d' => $issue_id));
+    return strtr($this->getTrackerUrl('tracker'), array('%d' => $issue_id));
   }
 }
diff --git includes/interfaces.inc includes/interfaces.inc
index 8ef4ffa..c5a559d 100644
--- includes/interfaces.inc
+++ includes/interfaces.inc
@@ -322,3 +322,82 @@ interface VersioncontrolAuthHandlerInterface {
    */
   public function getErrorMessages();
 }
+
+interface VersioncontrolWebviewerUrlHandlerInterface {
+
+  /**
+   * Retrieve the URL of the repository viewer that displays the given commit
+   * in the corresponding repository.
+   *
+   * @param $revision
+   *   The revision on the commit operation whose view URL should be retrieved.
+   *
+   * @return
+   *   The commit view URL corresponding to the given arguments.
+   *   An empty string is returned if no commit view URL has been defined,
+   *   or if the commit cannot be viewed for any reason.
+   */
+  public function getCommitViewUrl($revision);
+
+  /**
+   * Retrieve the URL of the repository viewer that displays the commit log
+   * of the given item in the corresponding repository. If no such URL has been
+   * specified by the user, the appropriate URL from the Commit Log module is
+   * used as a fallback (if that module is enabled).
+   *
+   * @param $item
+   *   The item whose log view URL should be retrieved.
+   *
+   * @return
+   *   The item log view URL corresponding to the given arguments.
+   *   An empty string is returned if no item log view URL has been defined
+   *   (and if not even Commit Log is enabled), or if the item cannot be viewed
+   *   for any reason.
+   */
+  public function getItemLogViewUrl(&$item);
+
+  /**
+   * Retrieve the URL of the repository viewer that displays the contents of the
+   * given item in the corresponding repository.
+   *
+   * @param $item
+   *   The item whose view URL should be retrieved.
+   *
+   * @return
+   *   The item view URL corresponding to the given arguments.
+   *   An empty string is returned if no item view URL has been defined,
+   *   or if the item cannot be viewed for any reason.
+   */
+  public function getItemViewUrl(&$item);
+
+  /**
+   * Retrieve the URL of the repository viewer that displays the diff between
+   * two given files in the corresponding repository.
+   *
+   * @param $file_item_new
+   *   The new version of the file that should be diffed.
+   * @param $file_item_old
+   *   The old version of the file that should be diffed.
+   *
+   * @return
+   *   The diff URL corresponding to the given arguments.
+   *   An empty string is returned if no diff URL has been defined,
+   *   or if the two items cannot be diffed for any reason.
+   */
+  public function getDiffUrl(&$file_item_new, $file_item_old);
+
+  /**
+   * Retrieve the URL of the issue tracker that displays the issue/case/bug page
+   * of an issue id which presumably has been mentioned in a commit message.
+   * As issue tracker URLs are specific to each repository, this also needs
+   * to be given as argument.
+   *
+   * @param $issue_id
+   *   A number that uniquely identifies the mentioned issue/case/bug.
+   *
+   * @return
+   *   The issue tracker URL corresponding to the given arguments.
+   *   An empty string is returned if no issue tracker URL has been defined.
+   */
+  public function getTrackerUrl($issue_id);
+}
diff --git includes/plugins/webviewer_url_handlers/gitweb.inc includes/plugins/webviewer_url_handlers/gitweb.inc
new file mode 100644
index 0000000..b269809
--- /dev/null
+++ includes/plugins/webviewer_url_handlers/gitweb.inc
@@ -0,0 +1,93 @@
+<?php
+// $Id$
+
+// This plugin contains the main documentation of how to make
+// webviewer_url_handler plugins until we make real documentation.
+
+$plugin = array(
+  'title' => t('Gitweb URL autogenerator'),
+  'url_templates' => array(
+
+    /**
+     * Template url for the commit view.
+     *
+     * The URL of the repository viewer that displays a given commit in the
+     * repository.
+     * It contains the following placeholders:
+     * - "%revision" for the revision/commit/changeset identifier.
+     */
+    'commit_view' => 'hola',
+
+    /**
+     * Template url for the file log view.
+     *
+     * The URL of the repository viewer that displays the commit log of
+     * a given file in the repository.
+     * It contains the following placeholders:
+     * - "%path" for the file path
+     * - "%revision" will be replaced by the file-level revision (the one
+     *   in {versioncontrol_item_revisions}.revision)
+     * - "%branch" will be replaced by the branch name that the file is on
+     */
+    'file_log_view' => '',
+
+    /**
+     * Template url for the file view.
+     *
+     * The URL of the repository viewer that displays the contents of a
+     * given file in the repository.
+     * It contains the following placeholders:
+     * - "%path" for the file path
+     * - "%revision" will be replaced by the file-level revision (the
+     *   one in {versioncontrol_item_revisions}.revision)
+     * - "%branch" will be replaced by the branch name that the file is on
+     */
+    'file_view' => '',
+
+    /**
+     * Template url for the directory view.
+     *
+     * The URL of the repository viewer that displays the contents of a given
+     * directory in the repository.
+     * It contains the following placeholders:
+     * - "%path" for the directory path
+     * - "%revision" will be replaced by the file-level revision (the
+     *   one in {versioncontrol_item_revisions}.revision - only makes sense
+     *   if directories are versioned, of course)
+     * - "%branch" will be replaced by the branch name that the
+     *   directory is on.
+     */
+    'directory_view' => '',
+
+    /**
+     * Template url for the diff view.
+     *
+     * The URL of the repository viewer that displays the diff between two
+     * given files in the repository.
+     * It contains the following placeholders:
+     * - "%path" and "%old-path" for the new and old paths (for some
+     *   version control systems, like CVS, those paths will always be
+     *   the same).
+     * - "%new-revision" and "%old-revision" will be replaced by the
+     *   respective file-level revisions (from
+     *   {versioncontrol_item_revisions}.revision)
+     * - "%branch" will be replaced by the branch name that the file is on.
+     */
+    'diff' => '',
+
+    /**
+     * Template url for the issue tracker view.
+     *
+     * The URL of the issue tracker that displays the issue/case/bug page of
+     * an issue id which presumably has been mentioned in a commit message.
+     * As issue tracker URLs are likely specific to each repository, this is
+     * also a per-repository setting. (Although... maybe it would make sense
+     * to have per-project rather than per-repository. Oh well.)
+     */
+    'tracker' => ''
+
+  ),
+  'handler' => array(
+    'class' => 'VersioncontrolRepositoryUrlHandler',
+  ),
+);
diff --git includes/views/handlers/versioncontrol_handler_field_operation_revision.inc includes/views/handlers/versioncontrol_handler_field_operation_revision.inc
index 45ba0e5..c8fde26 100644
--- includes/views/handlers/versioncontrol_handler_field_operation_revision.inc
+++ includes/views/handlers/versioncontrol_handler_field_operation_revision.inc
@@ -7,16 +7,32 @@
  */
 class versioncontrol_handler_field_operation_revision extends views_handler_field {
   public $backends = NULL;
+  public $repos = array();
 
   function construct() {
     parent::construct();
     $this->backends = versioncontrol_get_backends();
   }
 
+  /**
+   * Get a repository of the @param $vcs type.
+   */
+  function getRepository($vcs, $repo_id) {
+    if (!isset($this->repos[$repo_id])) {
+      $this->repos[$repo_id] = $this->backends[$vcs]->loadEntity('repo', array($repo_id));
+    }
+    return $this->repos[$repo_id];
+  }
+
   function render($values) {
     $revision = $values->{$this->field_alias};
     $vcs = $values->{$this->aliases['vcs']};
+    $repo_id = $values->{$this->aliases['repo_id']};
+    var_dump($values);
     $revision = $this->backends[$vcs]->formatRevisionIdentifier($revision, 'short');
+    $repo = $this->getRepository($vcs, $repo_id);
+    var_dump($repo);
+    dpm($repo->getUrlHandler());
     return check_plain($revision);
   }
 }
diff --git includes/views/versioncontrol.views.inc includes/views/versioncontrol.views.inc
index 4de3c8f..c7a7c58 100755
--- includes/views/versioncontrol.views.inc
+++ includes/views/versioncontrol.views.inc
@@ -291,6 +291,7 @@ function versioncontrol_views_data() {
       'click sortable' => TRUE,
       'additional fields' => array(
         'vcs' => array('table' => 'versioncontrol_repositories', 'field' => 'vcs'),
+        'repo_id' => array('table' => 'versioncontrol_repositories', 'field' => 'repo_id'),
       ),
     ),
     'sort' => array(
@@ -461,6 +462,7 @@ function versioncontrol_views_data() {
       'click sortable' => TRUE,
       'additional fields' => array(
         'vcs' => array('table' => 'versioncontrol_repositories', 'field' => 'vcs'),
+        'repo_id' => array('table' => 'versioncontrol_repositories', 'field' => 'repo_id'),
       ),
     ),
     'sort' => array(
diff --git tests/VersioncontrolTestCase.test tests/VersioncontrolTestCase.test
index 4799be6..430d5d8 100644
--- tests/VersioncontrolTestCase.test
+++ tests/VersioncontrolTestCase.test
@@ -149,9 +149,14 @@ abstract class VersioncontrolTestCase extends DrupalWebTestCase {
       'auth_handler' => 'ffa',
       'author_mapper' => 'simple_mail',
       'committer_mapper' => 'simple_mail',
+      //FIXME use a general commitlog url handler
+      'webviewer_url_handler' => 'gitweb',
     );
 
     $data += $default_data;
+    if (!isset($data['data']['versioncontrol']['base_url'])) {
+      $data['data']['versioncontrol']['base_url'] = '';
+    }
     foreach ($default_plugins as $plugin_slot => $default_plugin) {
       if (empty($data['plugins'][$plugin_slot])) {
         $data['plugins'][$plugin_slot] = $default_plugin;
diff --git versioncontrol.admin.inc versioncontrol.admin.inc
index ac81a9d..debd50e 100644
--- versioncontrol.admin.inc
+++ versioncontrol.admin.inc
@@ -371,6 +371,31 @@ function versioncontrol_admin_repository_edit(&$form_state, $repository, $vcs =
     '#options' => versioncontrol_auth_handlers_get_names(),
   );
 
+  $repo_url_handler = $repository_exists ? $repository->getUrlHandler() : NULL;
+
+  $form['repository_urls'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Repository browser URL handler'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+    '#weight' => 5,
+  );
+  $form['repository_urls']['base_url'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Base URL'),
+    '#default_value' => isset($repo_url_handler) ? $repo_url_handler->base_url : '',
+    '#size' => 40,
+    '#maxlength' => 255,
+    '#description' => t('The URL that let you see the repository web viewer. Do not use a trailing slash.'),
+  );
+  $form['repository_urls']['url_handler'] = array(
+    '#type' => 'radios',
+    '#title' => t('Web viewer URL handler'),
+    '#description' =>  t('The handler which will  provide the URLs that will be used to add links to item and commit displays such as the commit log.'),
+    '#default_value' => $repository_exists ? $repository->plugins['webviewer_url_handler'] : 0,
+    '#options' => versioncontrol_webviewer_url_handlers_get_names(),
+  );
+
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Save repository'),
@@ -414,6 +439,7 @@ function versioncontrol_admin_repository_edit_submit($form, &$form_state) {
       'author_mapper' => $form_state['values']['author_mapper'],
       'committer_mapper' => $form_state['values']['committer_mapper'],
       'auth_handler' => $form_state['values']['auth_handler'],
+      'webviewer_url_handler' => $form_state['values']['url_handler'],
     );
   }
   else {
@@ -428,11 +454,14 @@ function versioncontrol_admin_repository_edit_submit($form, &$form_state) {
         'author_mapper' => $form_state['values']['author_mapper'],
         'committer_mapper' => $form_state['values']['committer_mapper'],
         'auth_handler' => $form_state['values']['auth_handler'],
+        'webviewer_url_handler' => $form_state['values']['url_handler'],
       ),
     );
     $repository = $backends[$form['#vcs']]->buildEntity('repo', $repository);
   }
 
+  $repository->data['versioncontrol']['base_url'] = $form_state['values']['base_url'];
+
   // Let other modules alter the repository array.
   foreach (module_implements('versioncontrol_repository_submit') as $module) {
     $function = $module .'_versioncontrol_repository_submit';
diff --git versioncontrol.module versioncontrol.module
index 3bcff80..3cdfa5d 100644
--- versioncontrol.module
+++ versioncontrol.module
@@ -1009,3 +1009,18 @@ function versioncontrol_auth_handlers_get_names() {
   asort($names);
   return $names;
 }
+
+/**
+ * Load the names of all 'webviewer_url_handlers' for use at forms.
+ */
+function versioncontrol_webviewer_url_handlers_get_names() {
+  ctools_include('plugins');
+
+  $names = array();
+  foreach (ctools_get_plugins('versioncontrol', 'webviewer_url_handlers') as $name => $plugin) {
+    $names[$name] = $plugin['title'];
+  }
+
+  asort($names);
+  return $names;
+}
