diff --git a/resources/static/dialog/test/qunit/browserid_unit_test.js b/resources/static/dialog/test/qunit/js/browserid_unit_test.js
similarity index 93%
rename from resources/static/dialog/test/qunit/browserid_unit_test.js
rename to resources/static/dialog/test/qunit/js/browserid_unit_test.js
index 5755fabc56122270993a990e6bea620d0c424eb5..840039df59b43dd36e016f6c23636bddcc784d55 100644
--- a/resources/static/dialog/test/qunit/browserid_unit_test.js
+++ b/resources/static/dialog/test/qunit/js/browserid_unit_test.js
@@ -34,10 +34,10 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
-steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid", function() {
+steal.plugins("jquery", "funcunit/qunit").then("/js/page_helpers", "/js/browserid", function() {
   "use strict";
 
-  module("browserid-unit");
+  module("/js/browserid");
   
 
 });
diff --git a/resources/static/dialog/test/qunit/js/page_helpers_unit_test.js b/resources/static/dialog/test/qunit/js/page_helpers_unit_test.js
new file mode 100644
index 0000000000000000000000000000000000000000..9f076596ea5b4691651f1e9fa7705923b556fc02
--- /dev/null
+++ b/resources/static/dialog/test/qunit/js/page_helpers_unit_test.js
@@ -0,0 +1,81 @@
+/*jshint browsers:true, forin: true, laxbreak: true */
+/*global steal: true, test: true, start: true, stop: true, module: true, ok: true, equal: true, BrowserID: true */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla BrowserID.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid", function() {
+  "use strict";
+
+  var pageHelpers = BrowserID.PageHelpers;
+
+  module("/js/page_helpers");
+  
+
+  test("setStoredEmail/getStoredEmail/setupEmail prefills the email address", function() {
+    $("#email").val("");
+
+    pageHelpers.setStoredEmail("testuser@testuser.com");
+    pageHelpers.setupEmail();
+
+    equal($("#email").val(), "testuser@testuser.com", "email was set on setupEmail");
+    equal(pageHelpers.getStoredEmail(), "testuser@testuser.com", "getStoredEmail works correctly");
+  });
+
+  test("a key press in the email address field saves it", function() {
+    $("#email").val("");
+
+    pageHelpers.setStoredEmail("testuser@testuser.co");
+    pageHelpers.setupEmail();
+
+    // The fake jQuery event does not actually cause the letter to be added, we 
+    // have to do that manually.
+    $("#email").val("testuser@testuser.com");
+
+    var e = jQuery.Event("keyup");
+    e.which = 77; //choose the one you want
+    e.keyCode = 77;
+    $("#email").trigger(e);
+
+    equal(pageHelpers.getStoredEmail(), "testuser@testuser.com", "hitting a key updates the stored email");
+  });
+
+  test("clearStoredEmail clears the email address from storage", function() {
+    pageHelpers.clearStoredEmail();
+
+    equal(pageHelpers.getStoredEmail(), "", "clearStoredEmail clears stored email");
+  });
+
+});
+
+
diff --git a/resources/static/dialog/test/qunit/qunit.js b/resources/static/dialog/test/qunit/qunit.js
index 55f9a46cf99b568c7226bfd4ac2408e1c44341e3..093568db7df89e758c8ecb875c6cf0b872acd0d4 100644
--- a/resources/static/dialog/test/qunit/qunit.js
+++ b/resources/static/dialog/test/qunit/qunit.js
@@ -17,7 +17,8 @@ steal("/dialog/resources/browserid.js",
          'pickemail.ejs',
          'offline.ejs',
          'error.ejs')
-  .then("browserid_unit_test")
+  .then("js/browserid_unit_test")
+  .then("js/page_helpers_unit_test")
   .then("include_unit_test")
   .then("relay/relay_unit_test")
   .then("pages/add_email_address_test")
diff --git a/resources/static/js/browserid.js b/resources/static/js/browserid.js
index d4006165827f2fe2105e55cffe500b28977fea34..217e7cd03418c7e26472497a271594b33589b11f 100644
--- a/resources/static/js/browserid.js
+++ b/resources/static/js/browserid.js
@@ -34,8 +34,6 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-window.BrowserID = window.BrowserID || {};
-
 $(function() {
   "use strict";
 
@@ -43,21 +41,11 @@ $(function() {
    * For the main page
    */
 
-  function getParameterByName( name ) {
-    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
-    var regexS = "[\\?&]"+name+"=([^&#]*)";
-    var regex = new RegExp( regexS );
-    var results = regex.exec( window.location.href );
-    if( results == null )
-      return "";
-    else
-      return decodeURIComponent(results[1].replace(/\+/g, " "));
-  }
-
-  var token = getParameterByName("token"),
-      path = document.location.pathname,
-      bid = BrowserID,
-      user = bid.User;
+  var bid = BrowserID,
+      pageHelpers = bid.PageHelpers,
+      user = bid.User,
+      token = pageHelpers.getParameterByName("token"),
+      path = document.location.pathname;
 
   if (!path || path === "/") {
     bid.index();
diff --git a/resources/static/js/page_helpers.js b/resources/static/js/page_helpers.js
new file mode 100644
index 0000000000000000000000000000000000000000..1e0bb323885460864dbb5ddd2582ff1504de1ccc
--- /dev/null
+++ b/resources/static/js/page_helpers.js
@@ -0,0 +1,93 @@
+/*globals BrowserID: true, _: true */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla BrowserID.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+BrowserID.PageHelpers = (function() {
+  "use strict";
+
+  var win = window,
+      locStorage = win.localStorage,
+      bid = BrowserID;
+
+  function setStoredEmail(email) {
+    locStorage.signInEmail = email;
+  }
+
+  function onEmailKeyUp(event) {
+    var email = $("#email").val();
+    setStoredEmail(email);
+  }
+
+  function prefillEmail() {
+    // If the user tried to sign in on the sign up page with an existing email, 
+    // place that email in the email field, then focus the password.
+    var el = $("#email"),
+        email = locStorage.signInEmail;
+
+    if (email) {
+      el.val(email);
+      if ($("#password").length) $("#password").focus();
+    }
+
+    el.keyup(onEmailKeyUp);
+  }
+  
+  function clearStoredEmail() {
+    locStorage.removeItem("signInEmail");
+  }
+
+  function getStoredEmail() {
+    return locStorage.signInEmail || "";
+  }
+
+  function getParameterByName( name ) {
+    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
+    var regexS = "[\\?&]"+name+"=([^&#]*)";
+    var regex = new RegExp( regexS );
+    var results = regex.exec( win.location.href );
+    if( results === null )
+      return "";
+    else
+      return decodeURIComponent(results[1].replace(/\+/g, " "));
+  }
+
+  return {
+    setupEmail: prefillEmail,
+    setStoredEmail: setStoredEmail,
+    clearStoredEmail: clearStoredEmail,
+    getStoredEmail: getStoredEmail,
+    getParameterByName: getParameterByName
+  };
+}());
diff --git a/resources/static/js/pages/forgot.js b/resources/static/js/pages/forgot.js
index 1ab1bb6f0d1b4a9732829c8b8f1ac8df2d8dbe01..b329a1da7e10f9cf156e5d88c8b702cd0f64adea 100644
--- a/resources/static/js/pages/forgot.js
+++ b/resources/static/js/pages/forgot.js
@@ -37,9 +37,14 @@
 BrowserID.forgot = (function() {
   "use strict";
 
+  var bid = BrowserID,
+      pageHelpers = bid.PageHelpers;
+
   return function() {
     $("form input[autofocus]").focus();
 
+    pageHelpers.setupEmail();
+
     $("#signUpForm").bind("submit", function(event) {
       event.preventDefault();
       $(".notifications .notification").hide();
@@ -53,7 +58,8 @@ BrowserID.forgot = (function() {
         return false;
       }
 
-      BrowserID.User.createUser(email, function onSuccess(keypair) {
+      pageHelpers.clearStoredEmail();
+      bid.User.createUser(email, function onSuccess(keypair) {
         $('#sent_to_email').html(email);
         $('#forminputs').fadeOut();
         $(".notifications .notification.emailsent").fadeIn();
diff --git a/resources/static/js/pages/signin.js b/resources/static/js/pages/signin.js
index 1df6ec7b827cf0eba6174b7a1d2d9301a58dfee2..69590b274a4aa2b63db65589d50d8bbd775a6958 100644
--- a/resources/static/js/pages/signin.js
+++ b/resources/static/js/pages/signin.js
@@ -39,23 +39,13 @@
 
   var bid = BrowserID,
       user = bid.User,
+      pageHelpers = bid.PageHelpers,
       validation = bid.Validation;
 
-  function prefillEmail() {
-    // If the user tried to sign in on the sign up page with an existing email, 
-    // place that email in the email field, then focus the password.
-    var email = window.localStorage.signInEmail;
-    if (email) {
-      $("#email").val(email);
-      window.localStorage.removeItem('signInEmail');
-      $("#password").focus();
-    }
-  }
-
   bid.signIn = function () {
     $("form input[autofocus]").focus();
 
-    prefillEmail();
+    pageHelpers.setupEmail();
 
     $("#signUpForm").bind("submit", function(event) {
       event.preventDefault();
@@ -68,6 +58,7 @@
       if (valid) {
         user.authenticate(email, password, function onSuccess(authenticated) {
           if (authenticated) {
+            pageHelpers.clearStoredEmail();
             document.location = "/";
           }
           else {
diff --git a/resources/static/js/pages/signup.js b/resources/static/js/pages/signup.js
index c60e3f01e88fb2145528ca7e67bf5dd254f2d04d..429fbccc66c0bfcb29a5eed5324101cee7ca9dcf 100644
--- a/resources/static/js/pages/signup.js
+++ b/resources/static/js/pages/signup.js
@@ -39,10 +39,10 @@
 
   var bid = BrowserID,
       user = bid.User,
+      pageHelpers = bid.PageHelpers,
       ANIMATION_SPEED = 250;
 
   bid.signUp = function () {
-
     function replaceWithMessage(selector) {
         $('.forminputs').fadeOut(ANIMATION_SPEED, function() {
           $(selector).fadeIn(ANIMATION_SPEED);
@@ -61,6 +61,8 @@
     $(function () {
       $("form input[autofocus]").focus();
 
+      pageHelpers.setupEmail();
+
       $("#email").bind("keyup", function(event) {
         if (event.which !== 13) {
           $(".notification").fadeOut(ANIMATION_SPEED);
@@ -79,6 +81,7 @@
 
         user.isEmailRegistered(email, function(registered) {
           if (!registered) {
+            pageHelpers.clearStoredEmail();
             user.createUser(email, function onSuccess(keypair) {
               $('#sentToEmail').html(email);
               replaceWithMessage(".emailsent");
@@ -87,7 +90,6 @@
           else {
             $('#registeredEmail').html(email);
             showNotice(".alreadyRegistered");
-            window.localStorage.signInEmail = email;
           }
         }, onFailure);
       });
diff --git a/resources/views/layout.ejs b/resources/views/layout.ejs
index 0a5c452ca86feb75de542a7d6085d887b8a7d521..af3a352a3c4093c020ffe79d1a51be8d784882d9 100644
--- a/resources/views/layout.ejs
+++ b/resources/views/layout.ejs
@@ -19,6 +19,8 @@
     <script src="/js/json2.js" type="text/javascript"></script>
     <script src="/dialog/resources/underscore-min.js" type="text/javascript"></script>
     <script src="/dialog/resources/browserid-extensions.js" type="text/javascript"></script>
+    <script src="/dialog/resources/browserid.js" type="text/javascript"></script>
+    <script src="/js/page_helpers.js" type="text/javascript"></script>
     <script src="/js/browserid.js" type="text/javascript"></script>
     <script src="/js/pages/index.js" type="text/javascript"></script>
     <script src="/dialog/resources/storage.js" type="text/javascript"></script>
diff --git a/scripts/compress.sh b/scripts/compress.sh
index 4ef16ff38447d650e359a7c9b99bb533b99047f3..6233646e5d25ab275e4efb3e87b30ae77697922e 100755
--- a/scripts/compress.sh
+++ b/scripts/compress.sh
@@ -50,7 +50,7 @@ echo ''
 
 cd ../js
 # re-minimize everything together
-cat jquery-1.6.2.min.js json2.js browserid.js ../dialog/resources/underscore-min.js ../dialog/resources/browserid-extensions.js ../dialog/resources/storage.js ../dialog/resources/network.js ../dialog/resources/user.js ../dialog/resources/tooltip.js ../dialog/resources/validation.js pages/index.js pages/add_email_address.js pages/verify_email_address.js pages/manage_account.js pages/signin.js pages/signup.js pages/forgot.js > lib.js
+cat jquery-1.6.2.min.js json2.js ../dialog/resources/browserid.js page_helpers.js browserid.js ../dialog/resources/underscore-min.js ../dialog/resources/browserid-extensions.js ../dialog/resources/storage.js ../dialog/resources/network.js ../dialog/resources/user.js ../dialog/resources/tooltip.js ../dialog/resources/validation.js pages/index.js pages/add_email_address.js pages/verify_email_address.js pages/manage_account.js pages/signin.js pages/signup.js pages/forgot.js > lib.js
 $UGLIFY < lib.js > lib.min.js
 
 cd ../css