diff --git modules/dashboard/dashboard.info modules/dashboard/dashboard.info
new file mode 100644
index 0000000..8aecfec
--- /dev/null
+++ modules/dashboard/dashboard.info
@@ -0,0 +1,9 @@
+; $Id$
+name = Dashboard
+description = A module that provides a dashboard interface for organizing and tracking various information within your site.
+core = 7.x
+package = Core
+version = VERSION
+files[] = dashboard.info
+files[] = dashboard.module
+dependencies[] = block
diff --git modules/dashboard/dashboard.js modules/dashboard/dashboard.js
new file mode 100644
index 0000000..f71a687
--- /dev/null
+++ modules/dashboard/dashboard.js
@@ -0,0 +1,95 @@
+// $Id: toolbar.js,v 1.1 2009/07/04 05:37:30 dries Exp $
+(function ($) {
+
+/**
+ * Implementation of Drupal.behaviors for dashboard.
+ */
+Drupal.behaviors.dashboard = {
+  attach: function () {
+    $('#content').append('<div class="customize"><input type="button" class="form-submit" value="' + Drupal.t('Customize') + '"></input></div>');
+    $('#content .customize input').click(Drupal.behaviors.dashboard.showDisabledBlocks);
+  },
+
+  /**
+   * Enter "customize" mode.
+   */
+  showDisabledBlocks: function () {
+    $('div.customize').load(Drupal.settings.dashboard.customize, Drupal.behaviors.dashboard.makeDraggable);
+    // Display help.
+    $('div#help').show();
+  },
+
+  /**
+   * Helper function for showDisabledBlocks; sets up drag-and-drop.
+   */
+  makeDraggable: function () {
+    // Empty dashboard regions won't render on the page, but we need them for
+    // drag-and drop.
+    var thick = $('#dashboard-thick');
+    if (!thick.length) {
+      $('#content').after('<div id="dashboard-thick"><div class="section region">');
+    }
+    var thin = $('#dashboard-thin');
+    if (!thin.length) {
+      $('#dashboard-thick').after('<div id="dashboard-thin"><div class="section region">');
+    }
+
+    // Initialize drag-and-drop.
+    var regions = $('div.region');
+    regions.sortable({
+      connectWith: regions,
+      cursor: 'move',
+      dropOnEmpty: true,
+      items: '>div.block, div.disabled-block',
+      opacity: 0.8,
+      update: Drupal.behaviors.dashboard.update
+    });
+  },
+
+  update: function (event, ui) {
+    var item = $(ui.item);
+
+    // If the user dragged a disabled block, load the block contents.
+    if (item.hasClass('disabled-block')) {
+      var module, delta, itemClass;
+      itemClass = item.attr('class');
+      // Determine the block module and delta.
+      module = itemClass.match(/\bmodule-(\S+)\b/)[1];
+      delta = itemClass.match(/\bdelta-(\S+)\b/)[1];
+
+      // Load the newly enabled block's content.
+      $("div.content", item).load(Drupal.settings.dashboard.blockContent + '/' + module + '/' + delta);
+      console.log(Drupal.settings.dashboard.blockContent + '/' + module + '/' + delta);
+      // Remove "disabled-block" from the item's class, so we don't reload its
+      // content the next time it's dragged.
+      item.attr('class', itemClass.replace(/\bdisabled-block\b/, ''));
+    }
+
+    // Let the server know what the new block order is.
+    $.post(Drupal.settings.dashboard.updatePath, {
+        'form_token': Drupal.settings.dashboard.formToken,
+        'regions': Drupal.behaviors.dashboard.getOrder
+      }
+    );
+  },
+
+  /**
+   * Return the current order of the blocks in each of the sortable regions,
+   * in query string format.
+   */
+  getOrder: function () {
+    var order = [];
+    $('div.region').each(function () {
+      var region = $(this).parent().attr('id').replace(/-/g, '_');
+      var blocks = $(this).sortable('toArray');
+      var i;
+      for (i = 0; i < blocks.length; i++) {
+        order.push(region + '[]=' + blocks[i]);
+      }
+    });
+    order = order.join('&');
+    return order;
+  }
+};
+
+})(jQuery);
diff --git modules/dashboard/dashboard.module modules/dashboard/dashboard.module
new file mode 100644
index 0000000..a4c17f8
--- /dev/null
+++ modules/dashboard/dashboard.module
@@ -0,0 +1,146 @@
+<?php
+// $Id$
+
+/**
+ * Implement hook_menu().
+ */
+function dashboard_menu() {
+  $items['admin/dashboard'] = array(
+    'title' => 'Dashboard',
+    'page callback' => 'dashboard_admin',
+    'access arguments' => array('access toolbar'),
+    'type' => MENU_CALLBACK,
+  );
+  $items['admin/dashboard/customize'] = array(
+    'page callback' => 'dashboard_show_disabled',
+    'access arguments' => array('access toolbar'),
+    'type' => MENU_CALLBACK,
+  );
+  $items['admin/dashboard/block-content'] = array(
+    'page callback' => 'dashboard_show_block_content',
+    'page arguments' => array(3, 4),
+    'access arguments' => array('access toolbar'),
+    'type' => MENU_CALLBACK,
+  );
+  $items['admin/dashboard/update'] = array(
+    'page callback' => 'dashboard_update',
+    'access arguments' => array('access toolbar'),
+    'type' => MENU_CALLBACK,
+  );
+  return $items;
+}
+
+/**
+ * Dashboard page callback.
+ */
+function dashboard_admin() {
+  drupal_add_js(drupal_get_path('module', 'dashboard') . '/dashboard.js');
+  drupal_add_js(array(
+    'dashboard' => array(
+      'customize' => url('admin/dashboard/customize'),
+      'blockContent' => url('admin/dashboard/block-content'),
+      'updatePath' => url('admin/dashboard/update'),
+      'formToken' => drupal_get_token('dashboard-update'),
+    ),
+  ), array('type' => 'setting'));
+  drupal_add_library('system', 'ui.sortable');
+  drupal_add_library('system', 'ui.draggable');
+  drupal_add_library('system', 'ui.droppable');
+  return '';
+}
+
+/**
+ * Implement hook_block_list_alter().
+ *
+ * Skip rendering dashboard blocks when not on the dashboard page itself.
+ */
+function dashboard_block_list_alter(&$blocks) {
+  if ($_GET['q'] != 'admin/dashboard') {
+    foreach ($blocks as $key => $block) {
+      if (strpos($block->region, 'dashboard') === 0) {
+        unset($blocks[$key]);
+      }
+    }
+  }
+}
+
+function dashboard_show_disabled() {
+  global $theme_key;
+
+  // Theme system not initialized at this point.
+  drupal_theme_initialize();
+
+  // Blocks are not necessarily initialized either.
+  $blocks = _block_rehash();
+
+  $output = "<h2>Drag and drop dashboard widgets to their place.</h2>";
+  $output .= '<div id="disabled-blocks" class="clearfix"><div class="section region disabled-blocks">';
+  $output .= '<h3>Available blocks</h3>';
+
+  foreach ($blocks as $block) {
+    if ($block['theme'] == $theme_key && ($block['status'] == 0 || empty($block['region']))) {
+      $output .= '<div id="block-' . $block['module'] . '-' . $block['delta']
+      . '" class="disabled-block block block-' . $block['module'] . '-' . $block['delta']
+      . ' module-'.$block['module'].' delta-'.$block['delta'].'">'
+      . '<h2>'.(!empty($block['title']) ? $block['title'] : $block['info']).'</h2>'
+      . '<div class="content"></div>'
+      . '</div>';
+    }
+  }
+  $output .= '</div></div>';
+  
+  print $output;
+  exit();
+  
+}
+
+function dashboard_show_block_content($module, $delta) {
+  $block = module_invoke($module, 'block_view', $delta);
+  // TODO: Render the content portion of the block.
+  $rendered_block = '';
+  print $rendered_block;
+  exit;
+}
+
+/**
+ * Set the new weight of each region according to the drag-and-drop order.
+ */
+function dashboard_update() {
+  drupal_theme_initialize();
+  global $theme_key;
+  // Check the form token to make sure we have a valid request.
+  if (!empty($_REQUEST['form_token']) && drupal_valid_token($_REQUEST['form_token'], 'dashboard-update')) {
+    parse_str($_REQUEST['regions'], $regions);
+    foreach ($regions as $region_name => $blocks) {
+      if ($region_name == 'disabled_blocks') {
+        $region_name = '';
+      }
+      foreach ($blocks as $weight => $block_string) {
+        // Parse the query string to determine the block's module and delta.
+        preg_match('/block-([^-]+)-(.+)/', $block_string, $matches);
+        $block = new stdClass;
+        $block->module = $matches[1];
+        $block->delta = $matches[2];
+
+        $block->region = $region_name;
+        $block->weight = $weight;
+        $block->status = 1;
+
+        db_merge('block')
+          ->key(array(
+            'module' => $block->module,
+            'delta' => $block->delta,
+            'theme' => $theme_key,
+          ))
+          ->fields(array(
+            'status' => $block->status,
+            'weight' => $block->weight,
+            'region' => $block->region,
+            'pages' => '',
+          ))
+          ->execute();
+      }
+    }
+  }
+  exit;
+}
\ No newline at end of file
diff --git modules/toolbar/toolbar.install modules/toolbar/toolbar.install
index 42dadd2..edcf485 100644
--- modules/toolbar/toolbar.install
+++ modules/toolbar/toolbar.install
@@ -27,7 +27,7 @@ function toolbar_install() {
   $items = array(
     'node/add' => 'Add',
     'admin/content' => 'Find content',
-    'admin' => 'Dashboard',
+    'admin/dashboard' => 'Dashboard',
   );
   $weight = -20;
   foreach ($items as $path => $title) {
diff --git profiles/default/default.info profiles/default/default.info
index 9ebf79a..f0fecf0 100644
--- profiles/default/default.info
+++ profiles/default/default.info
@@ -6,6 +6,7 @@ core = 7.x
 dependencies[] = block
 dependencies[] = color
 dependencies[] = comment
+dependencies[] = dashboard
 dependencies[] = help
 dependencies[] = image 
 dependencies[] = menu
diff --git themes/seven/page-admin-dashboard.tpl.php themes/seven/page-admin-dashboard.tpl.php
new file mode 100644
index 0000000..161c5fa
--- /dev/null
+++ themes/seven/page-admin-dashboard.tpl.php
@@ -0,0 +1,62 @@
+<?php
+// $Id: page.tpl.php,v 1.1 2009/07/31 19:35:57 dries Exp $
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
+  "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $language->language; ?>" dir="<?php print $language->dir; ?>"
+  <?php print $rdf_namespaces; ?>>
+  <head profile="<?php print $grddl_profile; ?>">
+    <title><?php print $head_title; ?></title>
+    <?php print $head; ?>
+    <?php print $styles; ?>
+    <?php print $scripts; ?>
+    <?php print $ie_styles; ?>
+  </head>
+  <body class="<?php print $classes; ?>">
+
+  <?php print $page_top; ?>
+
+  <div id="branding" class="clearfix">
+    <?php print $breadcrumb; ?>
+    <?php if ($title): ?><h1 class="page-title"><?php print $title; ?></h1><?php endif; ?>
+    <?php if ($primary_local_tasks): ?><ul class="tabs primary"><?php print $primary_local_tasks; ?></ul><?php endif; ?>
+  </div>
+
+  <div id="page">
+    <?php if ($secondary_local_tasks): ?><ul class="tabs secondary"><?php print $secondary_local_tasks; ?></ul><?php endif; ?>
+
+    <div id="content">
+      <?php if ($show_messages && $messages): ?>
+        <div id="console" class="clearfix"><?php print $messages; ?></div>
+      <?php endif; ?>
+      <?php if ($help): ?>
+        <div id="help">
+          <?php print $help; ?>
+        </div>
+      <?php endif; ?>
+      <?php print $content; ?>
+    </div>
+    <?php if ($dashboard_thick): ?>
+      <div id="dashboard-thick">
+        <div class="section region">
+          <?php print $dashboard_thick; ?>
+        </div>
+      </div>
+    <?php endif; ?>
+    <?php if ($dashboard_thin): ?>
+      <div id="dashboard-thin">
+        <div class="section region">
+          <?php print $dashboard_thin; ?>
+        </div>
+      </div>
+    <?php endif; ?>
+
+    <div id="footer">
+      <?php print $feed_icons; ?>
+    </div>
+
+  </div>
+
+  <?php print $page_bottom; ?>
+
+  </body>
+</html>
\ No newline at end of file
diff --git themes/seven/seven.info themes/seven/seven.info
index da9e494..f42ec45 100644
--- themes/seven/seven.info
+++ themes/seven/seven.info
@@ -11,3 +11,7 @@ regions[content] = Content
 regions[help] = Help
 regions[page_top] = Page top
 regions[page_bottom] = Page bottom
+regions[dashboard_thick] = Dashboard thick
+regions[dashboard_thin] = Dashboard thin
+;hidden_regions[] = dashboard_thick
+;hidden_regions[] = dashboard_thin
diff --git themes/seven/style.css themes/seven/style.css
index c402743..90103ac 100644
--- themes/seven/style.css
+++ themes/seven/style.css
@@ -728,3 +728,74 @@ body.overlay #page {
 body.overlay #block-system-main {
   padding: 20px;
 }
+
+/* Dashboard */
+
+body.page-admin-dashboard div#page {
+  padding-top:20px;
+}
+
+body.page-admin-dashboard div#dashboard-thick {
+  width: 65%;
+  float: left;
+  min-height: 1px;
+  margin: 5px;
+}
+
+body.page-admin-dashboard div#dashboard-thin {
+  width: 30%;
+  float: left;
+  min-height: 1px;
+  margin: 5px;
+}
+
+body.page-admin-dashboard div.block {
+  border: 1px solid #e2e1dc;
+  margin-bottom: 20px;
+}
+
+body.page-admin-dashboard div.block h2 {
+  background-color:#e2e1dc;
+  padding: 3px 5px;
+}
+
+body.page-admin-dashboard div.block div.content {
+  padding: 10px 5px 5px 5px;
+}
+
+body.page-admin-dashboard div.block div.content ul.menu {
+  margin-left:20px;
+}
+
+body.page-admin-dashboard.one-sidebar div#content div.block {
+  margin-right:20px;
+}
+
+body.page-admin-dashboard #disabled-blocks {
+  margin: 5px;
+}
+body.page-admin-dashboard #disabled-blocks .block {
+  background: #e2e1dc;
+  padding: 4px;
+  margin: 3px;
+  display: inline;
+  -moz-border-radius: 4px;
+}
+body.page-admin-dashboard .ui-sortable {
+  border: 3px dashed #ccc;
+  padding: 10px;
+}
+body.page-admin-dashboard div.dragging {
+  width: 30% !important;
+}
+body.page-admin-dashboard #disabled-blocks h2 {
+  display: inline;
+  font-weight: normal;
+  white-space: nowrap;
+}
+body.page-admin-dashboard #disabled-blocks .block .content {
+  display: none;
+}
+body.page-admin-dashboard .ui-sortable .block {
+  cursor: move;
+}
