diff --git a/browserid/static/dialog/controllers/authenticate_controller.js b/browserid/static/dialog/controllers/authenticate_controller.js
index f9e96652556fda4cc528fa7d24b1d3467713a224..2e46165781876c56e2b88044d71b22d0ec0007eb 100644
--- a/browserid/static/dialog/controllers/authenticate_controller.js
+++ b/browserid/static/dialog/controllers/authenticate_controller.js
@@ -13,6 +13,14 @@
       });
     },
 
+    "#forgotpassword click": function(event) {
+      this.close("authenticate:forgotpassword");
+    },
+            
+    "#create click": function(event) {
+      this.close("authenticate:createuser");
+    },
+
     validate: function() {
       var email = $("#email_input").val();
       var pass = $("#password_input").val();
diff --git a/browserid/static/dialog/controllers/checkregistration_controller.js b/browserid/static/dialog/controllers/checkregistration_controller.js
index 6e8aaab6847bb5c4c3efad7e2239189774a926d5..7211dacf937e274e8e11f2369fddee9a03f81ed6 100644
--- a/browserid/static/dialog/controllers/checkregistration_controller.js
+++ b/browserid/static/dialog/controllers/checkregistration_controller.js
@@ -34,9 +34,6 @@
             //   'pending'  - a registration is in progress
             //   'noRegistration' - no registration is in progress
             if (status === 'complete') {
-              // this is a secondary registration from browserid.org, persist
-              // email, keypair, and that fact
-              
               // and tell the user that everything is really quite awesome.
               self.find("#waiting_confirmation").hide();
               self.find("#resendit_action").hide();
@@ -46,7 +43,6 @@
               $('#continue_button').removeClass('disabled');
 
               self.publish("checkregistration:confirmed");
-
             } else if (status === 'pending') {
               // try again, what else can we do?
               self.setupRegCheck();
@@ -66,13 +62,14 @@
     },
 
     validate: function() {
-      return !$("#continue_button").hasClass("disabled");
+      var valid = !$("#continue_button").hasClass("disabled");
+      return valid;
     },
 
     submit: function() {
       var self=this;
-      self._super();      
       self.publish("checkregistration:confirmed");
+      self._super();      
     }
 
   });
diff --git a/browserid/static/dialog/controllers/createaccount_controller.js b/browserid/static/dialog/controllers/createaccount_controller.js
index 26d2b0e67273280258f4fc61af2c84fe664b8871..591acc51220056d40aa8be9cfae090af06d1888a 100644
--- a/browserid/static/dialog/controllers/createaccount_controller.js
+++ b/browserid/static/dialog/controllers/createaccount_controller.js
@@ -13,7 +13,7 @@
         $('#create_continue').addClass('disabled');
 
         // watch input dialogs
-        this.checkEmail();      
+        this.setupWatchers();      
       },
 
       validate: function() {
@@ -45,7 +45,7 @@
         
       },
 
-      checkEmail: function() {
+      setupWatchers: function() {
         var checkedEmails = {};
         var emailCheckState = null;
         var nextEmailToCheck = null;
diff --git a/browserid/static/dialog/controllers/dialog_controller.js b/browserid/static/dialog/controllers/dialog_controller.js
index 972cc9c9d37c04f3d8163908d58d88ffeacfdf4a..043787c8937cf7ce84cb973a4ed3f4eb34690832 100644
--- a/browserid/static/dialog/controllers/dialog_controller.js
+++ b/browserid/static/dialog/controllers/dialog_controller.js
@@ -1,4 +1,4 @@
-/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */                                             
+/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */                                             
 /*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, runErrorDialog:true */ 
 //
 // a JMVC controller for the browserid dialog
@@ -85,6 +85,7 @@ $.Controller("Dialog", {}, {
       BrowserIDNetwork.logout(this.doAuthenticate.bind(this));
     },
       
+    /*
     "#create click": function(event) {
       this.doCreate();
     },
@@ -92,7 +93,7 @@ $.Controller("Dialog", {}, {
     "#forgotpassword click": function(event) {
       this.doForgotPassword();
     },
-            
+      */      
     "#cancel click": function(event) {
       this.onerror("canceled");
     },
@@ -101,13 +102,6 @@ $.Controller("Dialog", {}, {
       this.doStart();
     },
 
-    /*
-    "#continue_button click": function(event) {
-      if (!$("#continue_button").hasClass('disabled')) {
-        this.doSignIn();
-      }
-    },
-*/
     getVerifiedEmail: function(origin_url, onsuccess, onerror) {
       this.onsuccess = onsuccess;
       this.onerror = onerror;
@@ -134,7 +128,18 @@ $.Controller("Dialog", {}, {
         self.syncIdentities();
       });
 
+      hub.subscribe("authenticate:createuser", function() {
+        self.doCreate();
+      });
+
+      hub.subscribe("authenticate:forgotpassword", function() {
+        self.doForgotPassword();
+      });
+
+
       hub.subscribe("checkregistration:confirmed", function() {
+        // this is a secondary registration from browserid.org, persist
+        // email, keypair, and that fact
         self.persistAddressAndKeyPair(self.confirmEmail, 
           self.confirmKeypair, "browserid.org:443");
         self.syncidentities();
@@ -188,6 +193,8 @@ $.Controller("Dialog", {}, {
     },
       
     doForgotPassword: function() {
+      this.element.forgotpassword();
+/*
       this.renderTemplates("forgotpassword.ejs", {},
                            "bottom-continue.ejs", {});
 
@@ -218,6 +225,7 @@ $.Controller("Dialog", {}, {
       
       // do a check at load time, in case the user is using the back button (enables the continue button!)
       checkInput();
+      */
     },
 
     doWait: function(info) {
diff --git a/browserid/static/dialog/controllers/forgotpassword_controller.js b/browserid/static/dialog/controllers/forgotpassword_controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..bb5805c6d39a5ee9091e26c865ddfec14b91faba
--- /dev/null
+++ b/browserid/static/dialog/controllers/forgotpassword_controller.js
@@ -0,0 +1,78 @@
+(function() {
+  "use strict";
+
+  PageController.extend("Forgotpassword", {}, {
+      init: function() {
+        this._super({
+          bodyTemplate: "forgotpassword.ejs",
+          bodyVars: {},
+          footerTemplate: "bottom-continue.ejs",
+          footerVars: {}
+        });
+
+        $("#create_continue").addClass("disabled");
+        
+        this.setupWatchers();
+      },
+
+      setupWatchers: function() {
+        var self=this;
+        function checkInput() {
+          var pass = $("#password_input").val();
+          var match = pass === $("#password_verify_input").val();
+          self.find(".passwordnote").hide();
+          $("#create_continue").addClass("disabled");
+          if (!match) {
+            self.find("#passwords_different").show();
+          } else {
+            if (!pass) {
+              self.find("#enter_a_password").show();
+            } else if (pass.length < 5) {
+              self.find("#password_too_short").show();
+            } else {
+              self.find("#password_ok").show();
+              $("#create_continue").removeClass("disabled");
+            }
+          }
+        }
+        
+        // watch input dialogs
+        self.find("input").unbind("keyup").bind("keyup", checkInput);
+        
+        // do a check at load time, in case the user is using the back button (enables the continue button!)
+        checkInput();
+
+      },
+
+      validate: function() {
+        if ($("#create_continue").hasClass("disabled"))
+          return false;
+        return true;
+      },
+
+      submit: function() {
+        // now we need to actually try to stage the creation of this account.
+        var email = this.find("#email_input").val();
+        var pass = this.find("#password_input").val();
+        var keypair = CryptoStubs.genKeyPair();
+
+        this.doWait(BrowserIDWait.createAccount);
+
+        var self = this;
+        BrowserIDNetwork.stageUser(email, pass, keypair, function() {
+            self.close("createaccount:created", {
+              email: email,
+              keypair: keypair
+            });
+          },
+          function() {
+            self.runErrorDialog(BrowserIDErrors.createAccount);
+          }
+        );
+      }
+
+  });
+
+}());
+
+
diff --git a/browserid/static/dialog/dialog.js b/browserid/static/dialog/dialog.js
index 52f97f8d1811dfffc90a3e3c9398df2a723f8075..b1efa30d611fbb0915a56311eb9681d9b51e352a 100644
--- a/browserid/static/dialog/dialog.js
+++ b/browserid/static/dialog/dialog.js
@@ -24,7 +24,8 @@ steal.plugins(
                'page',
                'authenticate',
                'createaccount',
-               'checkregistration')					// loads files in controllers folder
+               'checkregistration',
+               'forgotpassword')					// loads files in controllers folder
 
 	.views('authenticate.ejs',
            'addemail.ejs',